vue cli4 vue.config.js設定詳解

2020-08-12 18:45:09

vue.config.js 建立的時候沒有,需要手動建立

const path = require('path');
const webpack = require('webpack');
const UglifyPlugin = require('uglifyjs-webpack-plugin');
const CompressionPlugin = require("compression-webpack-plugin");
// const PurgeCssWebpackPlugin = require("purgecss-webpack-plugin"); // 主要的作用刪除無意義的css,只能配合 mini-css-extract-plugin
// const glob = require("glob"); // 主要功能就是查詢匹配的檔案,配合PurgeCssWebpackPlugin
const {
  BundleAnalyzerPlugin
} = require('webpack-bundle-analyzer');
const OptimizeCssAssetsPlugin = require('optimize-css-assets-webpack-plugin'); //壓縮css外掛
//const AddCdnPlguin = require("add-asset-html-cdn-webpack-plugin");
const HtmlWebpackPlugin = require('html-webpack-plugin')
//const SpeedMeasureWebpackPlugin = require('speed-measure-webpack-plugin');
// const smw = new SpeedMeasureWebpackPlugin();
let {
  version,
  openGizp
} = require('./package.json'); //版本號和是否開啓壓縮
const production = process.env.NODE_ENV != 'development';
let buildReport = process.env.npm_lifecycle_event.includes('build:report'); //是否顯示打包分析介面
// const ExtractTextPlugin = require('extract-text-webpack-plugin');
// var OptimizeCssAssetsPlugin = require('optimize-css-assets-webpack-plugin');
function resolve(dir) {
  return path.join(__dirname, dir) //此處使用path.resolve 或path.join 可自行調整
}
module.exports = {
  // 基本路徑
  publicPath: production ? '' : '/',
  // devtool: production ? 'none' : 'source-map',
  // 輸出檔案目錄
  outputDir: 'dist',
  assetsDir: './', //放置生成的靜態資源 (js、css、img、fonts) 的 (相對於 outputDir 的) 目錄。
  indexPath: 'index.html', //指定生成的 index.html 的輸出路徑 (相對於 outputDir)。也可以是一個絕對路徑。
  // 生產環境是否生成 sourceMap 檔案
  productionSourceMap: false,
  //   pages: {
  //     index: {
  //         entry: 'src/main.js', // page 的入口
  //         template: 'public/index.html', // 模板來源
  //         filename: 'index.html', // 在 dist/index.html 的輸出 
  //         title: 'Index Page', // 當使用 title 選項時,template 中的 title 標籤需要是 <title><%= htmlWebpackPlugin.options.title %></title>
  //         chunks: ['chunk-vendors', 'chunk-common', 'index'] // 在這個頁面中包含的塊,預設情況下會包含 // 提取出來的通用 chunk 和 vendor chunk。
  //     }
  //     //subpage: 'src/main.js' //不太理解
  //     // 當使用只有入口的字串格式時,
  //     // 模板會被推導爲 `public/subpage.html`
  //     // 並且如果找不到的話,就回退到 `public/index.html`。
  //     // 輸出檔名會被推導爲 `subpage.html`。

  // },
  lintOnSave: false,//設定是否在開發環境下每次儲存程式碼時都啓用 eslint驗證
  css: {
    loaderOptions: {
      //設定全域性scss變數或者mixin....
      sass: {
        //老版本是data,新版本是prependData
        prependData: `@import "@/style/global.scss";`,
      }
    },
    extract: false,
    sourceMap: false,
    requireModuleExtension: true,

  },
  filenameHashing: true, //檔案hash
  parallel: require('os').cpus().length > 1,
  devServer: {
    // publicPath: path.join(__dirname, "dist"),
    contentBase: path.resolve(__dirname, './dist'), // webpack啓動服務會在dist目錄下
    compress: true, //gzip 可以提升返回頁面的速度
    port: 8080,//伺服器埠號
    clientLogLevel: "none",
    // lazy: true,
    filename: "bundle.js",
    open: true,
    proxy: {
      "/api": {
        // target: "http://192.168.0.148:8080",
        target: "http://zhcl.4000750222.com/testCoupon/",
        pathRewrite: {
          "^/api": ""
        }
      }
    }
    //在本地伺服器開啓gzip,線上伺服器都支援gzip不需要設定
    //   before(app) {
    //     app.get(/.*.(js)$/, (req, res, next) => {
    //         req.url = req.url + '.gz';
    //         res.set('Content-Encoding', 'gzip');
    //         next();
    //     })
    // }
  },
  configureWebpack: (config) => {
    var optimization;
    if (production) {
      // 將每個依賴包打包成單獨的js檔案
      optimization = {
        minimizer: [
          // new UglifyPlugin({
          //   parallel: true,
          //   uglifyOptions: {
          //     mangle: true,
          //     output: { //刪除註釋
          //       comments: false
          //     },
          //     warnings: false,
          //     compress: {
          //       drop_console: true, // console
          //       drop_debugger: false,
          //       pure_funcs: ['console.log'] // 移除console
          //     }
          //   }
          // })


          // new OptimizeCssAssetsPlugin({
          //   assetNameRegExp: /\.css$/g, //一個正則表達式,指示應優化/最小化的資產的名稱。提供的正則表達式針對設定中ExtractTextPlugin範例導出的檔案的檔名執行,而不是源CSS檔案的檔名。預設爲/\.css$/g
          //   cssProcessor: require('cssnano'), //用於優化\最小化CSS的CSS處理器,預設爲cssnano
          //   cssProcessorOptions: {
          //     safe: true,
          //     discardComments: {
          //       removeAll: true
          //     }
          //   }, //傳遞給cssProcessor的選項,預設爲{}
          //   canPrint: true //一個布爾值,指示外掛是否可以將訊息列印到控制檯,預設爲true
          // }),
        ],
        runtimeChunk: 'single',
        splitChunks: {
          // inital 只操作同步的 all 所有的 async 非同步的
          chunks: "all", // 預設支援非同步的程式碼分割 import()
          minSize: 30000, // 檔案超過30k 我就會抽離他
          maxSize: 0,
          minChunks: 2, // 最少模組參照2次才抽離
          maxAsyncRequests: 5, // 最多5個請求
          maxInitialRequests: 3, // 最多首屏載入3個請求
          automaticNameDelimiter: "-", // xxx~a~b
          automaticNameMaxLength: 30, // 最長名字打大小
          name: true,
          // maxInitialRequests: 10,
          // minSize: 50000, // 依賴包超過20000bit將被單獨打包
          cacheGroups: {
            // vendor: {
            //   test: /[\\/]node_modules[\\/]/,
            //   name(module) {
            //     // get the name. E.g. node_modules/packageName/not/this/part.js
            //     // or node_modules/packageName
            //     const packageName = module.context.match(/[\\/]node_modules[\\/](.*?)([\\/]|$)/)[1]
            //     // npm package names are URL-safe, but some servers don't like @ symbols
            //     return `${packageName.replace('@', '')}`
            //   }
            // },
            vendor: {
              chunks: 'all',
              test: /node_modules/,
              name: 'vendor',
              minChunks: 1,
              maxInitialRequests: 5,
              minSize: 0,
              priority: 100
            },
            common: {
              chunks: 'all',
              test: /[\\/]src[\\/]js[\\/]/,
              name: 'common',
              minChunks: 2,
              maxInitialRequests: 5,
              minSize: 0,
              priority: 60
            },
            styles: {
              name: 'styles',
              test: /\.(sa|sc|c)ss$/,
              chunks: 'all',
              enforce: true
            },
            runtimeChunk: {
              name: 'manifest'
            }


          }
        }

      };
      Object.assign(config, {
        // externals: {
        //   'vue': 'Vue',
        //   'element-ui': 'ElementUI',
        //   'vue-router': 'VueRouter',
        //   'vuex': 'Vuex'
        //  },
        optimization,
        output: {
          ...config.output,
          filename: `js/[name].[chunkhash].${version}.js`,
          chunkFilename: `js/[name].[chunkhash].${version}.js`
        },
        plugins: [
          ...config.plugins,
          // new PurgeCssWebpackPlugin({
          //   paths: glob.sync('./src/**/*', {
          //     nodir: true
          //   }),
          //   extractors: [{
          //     extractor: class Extractor {
          //       static extract(content) {
          //         const validSection = content.replace(
          //           /<style([\s\S]*?)<\/style>+/gim,
          //           ""
          //         );
          //         return validSection.match(/[A-Za-z0-9-_:/]+/g) || [];
          //       }
          //     },
          //     extensions: ["html", "vue"]
          //   }],
          //   whitelist: ["html", "body"],
          //   whitelistPatterns: [/el-.*/],
          //   whitelistPatternsChildren: [/^token/, /^pre/, /^code/]
          // }),
          new OptimizeCssAssetsPlugin({
            assetNameRegExp: /\.css$/g, //一個正則表達式,指示應優化/最小化的資產的名稱。提供的正則表達式針對設定中ExtractTextPlugin範例導出的檔案的檔名執行,而不是源CSS檔案的檔名。預設爲/\.css$/g
            cssProcessor: require('cssnano'), //用於優化\最小化CSS的CSS處理器,預設爲cssnano
            cssProcessorOptions: {
              safe: true,
              discardComments: {
                removeAll: true
              }
            }, //傳遞給cssProcessor的選項,預設爲{}
            canPrint: true //一個布爾值,指示外掛是否可以將訊息列印到控制檯,預設爲true
          })

          // new webpack.ProvidePlugin({
          //   moment: "moment"
          // })
        ]
      })
    } else {
      // 爲開發環境修改設定...
    }
  },
  // transpileDependencies: ['webpack-dev-server/client'],
  chainWebpack: config => {
    if (production) {
      config.optimization.minimize(true);
      // config.plugin('cdn').use(
      //   new HtmlWebpackPlugin({
      //     title: '測試專案',
      //     template: resolve('./build_template/index.html'),
      //     // cdn(自定義屬性)載入的資源,不需要手動新增至index.html中,
      //     // 順序按陣列索引載入
      //     cdn: {
      //       css:['https://cdn.bootcss.com/element-ui/2.12.0/theme-chalk/index.css'],
      //       js: [
      //         'https://cdn.bootcss.com/vue/2.6.10/vue.min.js',
      //         'https://cdn.bootcss.com/element-ui/2.12.0/index.js',
      //         'https://cdn.bootcss.com/vue-router/3.0.0/vue-router.min.js',
      //         // 'https://cdn.bootcss.com/vuex/3.1.1/vuex.min.js',
      //         // "https://cdn.bootcss.com/vue/2.6.10/vue.min.js",
      //         // "https://cdn.bootcss.com/vue-router/3.0.2/vue-router.min.js",
      //         // "https://cdn.bootcss.com/element-ui/2.12.0/index.js",
      //         "https://cdn.bootcss.com/axios/0.19.0-beta.1/axios.min.js",
      //         "https://cdn.bootcss.com/echarts/4.2.1-rc1/echarts-en.common.min.js",
      //         "https://cdn.bootcss.com/moment.js/2.24.0/moment.min.js",
      //         "https://cdn.bootcss.com/mathjs/6.2.1/math.min.js",
      //         "https://cdn.bootcss.com/xlsx/0.14.3/xlsx.full.min.js"
      //       ]
      //     },
      //     minify: {
      //       //是否對大小寫敏感,預設false
      //      caseSensitive: true,

      //      //是否簡寫boolean格式的屬性如:disabled="disabled" 簡寫爲disabled  預設false
      //      collapseBooleanAttributes: true,

      //      //是否去除空格,預設false
      //      collapseWhitespace: true,

      //      //是否壓縮html裡的css(使用clean-css進行的壓縮) 預設值false;
      //      minifyCSS: true,

      //      //是否壓縮html裡的js(使用uglify-js進行的壓縮)
      //      minifyJS: true,

      //      //Prevents the escaping of the values of attributes
      //      preventAttributesEscaping: true,

      //      //是否移除屬性的引號 預設false
      //      removeAttributeQuotes: true,

      //      //是否移除註釋 預設false
      //      removeComments: true,

      //      //從指令碼和樣式刪除的註釋 預設false
      //      removeCommentsFromCDATA: true,

      //      //是否刪除空屬性,預設false
      //      removeEmptyAttributes: true,

      //      //  若開啓此項,生成的html中沒有 body 和 head,html也未閉合
      //      removeOptionalTags: false, 

      //      //刪除多餘的屬性
      //      removeRedundantAttributes: true, 

      //      //刪除script的型別屬性,在h5下面 下麪script的type預設值:text/javascript 預設值false
      //      removeScriptTypeAttributes: true,

      //      //刪除style的型別屬性, type="text/css" 同上
      //      removeStyleLinkTypeAttributes: true,

      //      //使用短的文件型別,預設false
      //      useShortDoctype: true,
      //      }
      //   })

      // )

      // config.plugin('css-assets').use(new OptimizeCssAssetsPlugin({
      //   assetNameRegExp: /\.css$/g, //一個正則表達式,指示應優化/最小化的資產的名稱。提供的正則表達式針對設定中ExtractTextPlugin範例導出的檔案的檔名執行,而不是源CSS檔案的檔名。預設爲/\.css$/g
      //   cssProcessor: require('cssnano'), //用於優化\最小化CSS的CSS處理器,預設爲cssnano
      //   cssProcessorOptions: {
      //     safe: true,
      //     discardComments: {
      //       removeAll: true
      //     }
      //   }, //傳遞給cssProcessor的選項,預設爲{}
      //   canPrint: true //一個布爾值,指示外掛是否可以將訊息列印到控制檯,預設爲true
      // }))
      if (buildReport) {
        config.plugin('webpack-report') // 打包分析
          .use(BundleAnalyzerPlugin, [{
             analyzerMode: 'static',
          }]);
      }
      if (openGizp) {
        config.plugin(openGizp).use(new CompressionPlugin({
          //test: /\.js$|\.html$|.\css/, //匹配檔名
          test: /\.(js|css|json|txt|html|svg|mp3)(\?.*)?$/i, //匹配檔名
          filename: '[path].gz[query]',
          algorithm: 'gzip',
          minRatio: 0.8,
          threshold: 10240, //對超過10k的數據壓縮
          deleteOriginalAssets: false //是否刪除原始檔
        }))
      }
      // 壓縮圖片

      config.module.rule("images")
      .use('url-loader')
        .loader('url-loader')
        .tap(options => Object.assign(options, { limit: 7000}))

    // config.module.rule('images')
    // .test(/\.(png|jpe?g|gif|svg)(\?.*)?$/)
    // .use('image-webpack-loader')
    // .loader('image-webpack-loader')
    // .options({ bypassOnDebug: true })


      // config.module
      // .rule("images")
      // .use("image-webpack-loader")
      // .loader("image-webpack-loader")
      // .options({
      //   mozjpeg: {
      //     progressive: true,
      //     quality: 65
      //   },
      //   optipng: {
      //     enabled: false
      //   },
      //   pngquant: {
      //     quality: [0.65, 0.90],
      //     speed: 4
      //   },
      //   gifsicle: {
      //     interlaced: false
      //   },
      //   webp: {
      //     quality: 75
      //   }
      // });
    }
    // config
    // .entry('index')
    // .add('babel-polyfill')
    // .end();
    // set('jquery$', 'jquery/dist/jquery.min.js');

    //設定音訊播放loader

    // 修復HMR
    config.resolve.symlinks(true);
    // 移除 prefetch 外掛
    config.plugins.delete('prefetch');
    // 移除 preload 外掛
    config.plugins.delete('preload');
    config.resolve.alias
      .set('@', resolve('src'))
      .set('@assets', resolve('./src/assets'))
  }
}