You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							253 lines
						
					
					
						
							7.5 KiB
						
					
					
				
			
		
		
	
	
							253 lines
						
					
					
						
							7.5 KiB
						
					
					
				const fs = require('fs') | 
						|
const path = require('path') | 
						|
const { semver, warn, pauseSpinner, resumeSpinner } = require('@vue/cli-shared-utils') | 
						|
 | 
						|
const findExisting = (context, files) => { | 
						|
  for (const file of files) { | 
						|
    if (fs.existsSync(path.join(context, file))) { | 
						|
      return file | 
						|
    } | 
						|
  } | 
						|
} | 
						|
 | 
						|
module.exports = (api, rootOptions) => { | 
						|
  api.chainWebpack(webpackConfig => { | 
						|
    const getAssetPath = require('../util/getAssetPath') | 
						|
    const shadowMode = !!process.env.VUE_CLI_CSS_SHADOW_MODE | 
						|
    const isProd = process.env.NODE_ENV === 'production' | 
						|
 | 
						|
    let sassLoaderVersion | 
						|
    try { | 
						|
      sassLoaderVersion = semver.major(require('sass-loader/package.json').version) | 
						|
    } catch (e) {} | 
						|
    if (sassLoaderVersion < 8) { | 
						|
      pauseSpinner() | 
						|
      warn('A new version of sass-loader is available. Please upgrade for best experience.') | 
						|
      resumeSpinner() | 
						|
    } | 
						|
 | 
						|
    const defaultSassLoaderOptions = {} | 
						|
    try { | 
						|
      defaultSassLoaderOptions.implementation = require('sass') | 
						|
      // since sass-loader 8, fibers will be automatically detected and used | 
						|
      if (sassLoaderVersion < 8) { | 
						|
        defaultSassLoaderOptions.fiber = require('fibers') | 
						|
      } | 
						|
    } catch (e) {} | 
						|
 | 
						|
    const { | 
						|
      extract = isProd, | 
						|
      sourceMap = false, | 
						|
      loaderOptions = {} | 
						|
    } = rootOptions.css || {} | 
						|
 | 
						|
    let { requireModuleExtension } = rootOptions.css || {} | 
						|
    if (typeof requireModuleExtension === 'undefined') { | 
						|
      if (loaderOptions.css && loaderOptions.css.modules) { | 
						|
        throw new Error('`css.requireModuleExtension` is required when custom css modules options provided') | 
						|
      } | 
						|
      requireModuleExtension = true | 
						|
    } | 
						|
 | 
						|
    const shouldExtract = extract !== false && !shadowMode | 
						|
    const filename = getAssetPath( | 
						|
      rootOptions, | 
						|
      `css/[name]${rootOptions.filenameHashing ? '.[contenthash:8]' : ''}.css` | 
						|
    ) | 
						|
    const extractOptions = Object.assign({ | 
						|
      filename, | 
						|
      chunkFilename: filename | 
						|
    }, extract && typeof extract === 'object' ? extract : {}) | 
						|
 | 
						|
    // use relative publicPath in extracted CSS based on extract location | 
						|
    const cssPublicPath = process.env.VUE_CLI_BUILD_TARGET === 'lib' | 
						|
      // in lib mode, CSS is extracted to dist root. | 
						|
      ? './' | 
						|
      : '../'.repeat( | 
						|
        extractOptions.filename | 
						|
            .replace(/^\.[\/\\]/, '') | 
						|
            .split(/[\/\\]/g) | 
						|
            .length - 1 | 
						|
      ) | 
						|
 | 
						|
    // check if the project has a valid postcss config | 
						|
    // if it doesn't, don't use postcss-loader for direct style imports | 
						|
    // because otherwise it would throw error when attempting to load postcss config | 
						|
    const hasPostCSSConfig = !!(loaderOptions.postcss || api.service.pkg.postcss || findExisting(api.resolve('.'), [ | 
						|
      '.postcssrc', | 
						|
      '.postcssrc.js', | 
						|
      'postcss.config.js', | 
						|
      '.postcssrc.yaml', | 
						|
      '.postcssrc.json' | 
						|
    ])) | 
						|
 | 
						|
    if (!hasPostCSSConfig) { | 
						|
      loaderOptions.postcss = { | 
						|
        plugins: [ | 
						|
          require('autoprefixer') | 
						|
        ] | 
						|
      } | 
						|
    } | 
						|
 | 
						|
    // if building for production but not extracting CSS, we need to minimize | 
						|
    // the embbeded inline CSS as they will not be going through the optimizing | 
						|
    // plugin. | 
						|
    const needInlineMinification = isProd && !shouldExtract | 
						|
 | 
						|
    const cssnanoOptions = { | 
						|
      preset: ['default', { | 
						|
        mergeLonghand: false, | 
						|
        cssDeclarationSorter: false | 
						|
      }] | 
						|
    } | 
						|
    if (rootOptions.productionSourceMap && sourceMap) { | 
						|
      cssnanoOptions.map = { inline: false } | 
						|
    } | 
						|
 | 
						|
    function createCSSRule (lang, test, loader, options) { | 
						|
      const baseRule = webpackConfig.module.rule(lang).test(test) | 
						|
 | 
						|
      // rules for <style lang="module"> | 
						|
      const vueModulesRule = baseRule.oneOf('vue-modules').resourceQuery(/module/) | 
						|
      applyLoaders(vueModulesRule, true) | 
						|
 | 
						|
      // rules for <style> | 
						|
      const vueNormalRule = baseRule.oneOf('vue').resourceQuery(/\?vue/) | 
						|
      applyLoaders(vueNormalRule, false) | 
						|
 | 
						|
      // rules for *.module.* files | 
						|
      const extModulesRule = baseRule.oneOf('normal-modules').test(/\.module\.\w+$/) | 
						|
      applyLoaders(extModulesRule, true) | 
						|
 | 
						|
      // rules for normal CSS imports | 
						|
      const normalRule = baseRule.oneOf('normal') | 
						|
      applyLoaders(normalRule, !requireModuleExtension) | 
						|
 | 
						|
      function applyLoaders (rule, isCssModule) { | 
						|
        if (shouldExtract) { | 
						|
          rule | 
						|
            .use('extract-css-loader') | 
						|
            .loader(require('mini-css-extract-plugin').loader) | 
						|
            .options({ | 
						|
              hmr: !isProd, | 
						|
              publicPath: cssPublicPath | 
						|
            }) | 
						|
        } else { | 
						|
          rule | 
						|
            .use('vue-style-loader') | 
						|
            .loader(require.resolve('vue-style-loader')) | 
						|
            .options({ | 
						|
              sourceMap, | 
						|
              shadowMode | 
						|
            }) | 
						|
        } | 
						|
 | 
						|
        const cssLoaderOptions = Object.assign({ | 
						|
          sourceMap, | 
						|
          importLoaders: ( | 
						|
            1 + // stylePostLoader injected by vue-loader | 
						|
            1 + // postcss-loader | 
						|
            (needInlineMinification ? 1 : 0) | 
						|
          ) | 
						|
        }, loaderOptions.css) | 
						|
 | 
						|
        if (isCssModule) { | 
						|
          cssLoaderOptions.modules = { | 
						|
            localIdentName: '[name]_[local]_[hash:base64:5]', | 
						|
            ...cssLoaderOptions.modules | 
						|
          } | 
						|
        } else { | 
						|
          delete cssLoaderOptions.modules | 
						|
        } | 
						|
 | 
						|
        rule | 
						|
          .use('css-loader') | 
						|
          .loader(require.resolve('css-loader')) | 
						|
          .options(cssLoaderOptions) | 
						|
 | 
						|
        if (needInlineMinification) { | 
						|
          rule | 
						|
            .use('cssnano') | 
						|
            .loader(require.resolve('postcss-loader')) | 
						|
            .options({ | 
						|
              sourceMap, | 
						|
              plugins: [require('cssnano')(cssnanoOptions)] | 
						|
            }) | 
						|
        } | 
						|
 | 
						|
        rule | 
						|
          .use('postcss-loader') | 
						|
          .loader(require.resolve('postcss-loader')) | 
						|
          .options(Object.assign({ sourceMap }, loaderOptions.postcss)) | 
						|
 | 
						|
        if (loader) { | 
						|
          let resolvedLoader | 
						|
          try { | 
						|
            resolvedLoader = require.resolve(loader) | 
						|
          } catch (error) { | 
						|
            resolvedLoader = loader | 
						|
          } | 
						|
 | 
						|
          rule | 
						|
            .use(loader) | 
						|
            .loader(resolvedLoader) | 
						|
            .options(Object.assign({ sourceMap }, options)) | 
						|
        } | 
						|
      } | 
						|
    } | 
						|
 | 
						|
    createCSSRule('css', /\.css$/) | 
						|
    createCSSRule('postcss', /\.p(ost)?css$/) | 
						|
    createCSSRule('scss', /\.scss$/, 'sass-loader', Object.assign( | 
						|
      {}, | 
						|
      defaultSassLoaderOptions, | 
						|
      loaderOptions.scss || loaderOptions.sass | 
						|
    )) | 
						|
    if (sassLoaderVersion < 8) { | 
						|
      createCSSRule('sass', /\.sass$/, 'sass-loader', Object.assign( | 
						|
        {}, | 
						|
        defaultSassLoaderOptions, | 
						|
        { | 
						|
          indentedSyntax: true | 
						|
        }, | 
						|
        loaderOptions.sass | 
						|
      )) | 
						|
    } else { | 
						|
      createCSSRule('sass', /\.sass$/, 'sass-loader', Object.assign( | 
						|
        {}, | 
						|
        defaultSassLoaderOptions, | 
						|
        loaderOptions.sass, | 
						|
        { | 
						|
          sassOptions: Object.assign( | 
						|
            {}, | 
						|
            loaderOptions.sass && loaderOptions.sass.sassOptions, | 
						|
            { | 
						|
              indentedSyntax: true | 
						|
            } | 
						|
          ) | 
						|
        } | 
						|
      )) | 
						|
    } | 
						|
    createCSSRule('less', /\.less$/, 'less-loader', loaderOptions.less) | 
						|
    createCSSRule('stylus', /\.styl(us)?$/, 'stylus-loader', Object.assign({ | 
						|
      preferPathResolver: 'webpack' | 
						|
    }, loaderOptions.stylus)) | 
						|
 | 
						|
    // inject CSS extraction plugin | 
						|
    if (shouldExtract) { | 
						|
      webpackConfig | 
						|
        .plugin('extract-css') | 
						|
          .use(require('mini-css-extract-plugin'), [extractOptions]) | 
						|
 | 
						|
      // minify extracted CSS | 
						|
      if (isProd) { | 
						|
        webpackConfig | 
						|
          .plugin('optimize-css') | 
						|
            .use(require('@intervolga/optimize-cssnano-plugin'), [{ | 
						|
              sourceMap: rootOptions.productionSourceMap && sourceMap, | 
						|
              cssnanoOptions | 
						|
            }]) | 
						|
      } | 
						|
    } | 
						|
  }) | 
						|
}
 | 
						|
 |