| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229 | const fs = require('fs')const path = require('path')const semver = require('semver')const findExisting = (context, files) => {  for (const file of files) {    if (fs.existsSync(path.join(context, file))) {      return file    }  }}module.exports = (api, options) => {  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) {}    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 {      modules = false,      extract = isProd,      sourceMap = false,      loaderOptions = {}    } = options.css || {}    const shouldExtract = extract !== false && !shadowMode    const filename = getAssetPath(      options,      `css/[name]${options.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 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 (options.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, modules)      function applyLoaders (rule, modules) {        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('vue-style-loader')            .options({              sourceMap,              shadowMode            })        }        const cssLoaderOptions = Object.assign({          sourceMap,          importLoaders: (            1 + // stylePostLoader injected by vue-loader            (hasPostCSSConfig ? 1 : 0) +            (needInlineMinification ? 1 : 0)          )        }, loaderOptions.css)        if (modules) {          const {            localIdentName = '[name]_[local]_[hash:base64:5]'          } = loaderOptions.css || {}          Object.assign(cssLoaderOptions, {            modules,            localIdentName          })        }        rule          .use('css-loader')          .loader('css-loader')          .options(cssLoaderOptions)        if (needInlineMinification) {          rule            .use('cssnano')            .loader('postcss-loader')            .options({              sourceMap,              plugins: [require('cssnano')(cssnanoOptions)]            })        }        if (hasPostCSSConfig) {          rule            .use('postcss-loader')            .loader('postcss-loader')            .options(Object.assign({ sourceMap }, loaderOptions.postcss))        }        if (loader) {          rule            .use(loader)            .loader(loader)            .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: options.productionSourceMap && sourceMap,              cssnanoOptions            }])      }    }  })}
 |