Webpack configuration in the vue.config.js file, webpack multiple application scenario configuration, optimization and multi-page application development

Table of contents

  • 1. Commonly used configurations in vue.config.js
    • 1. Export module
    • 2. PublicPath is the basic Url for deploying the application package
    • 3. outputDir output file directory
    • 4. assetsDir static resource directory generated after packaging
    • 5、lintOnSave
    • 6. productionSourceMap The source map of the production environment
    • 7、devServer
    • 8. chainWebpack webpack configuration
    • 9. configureWebpack webpack configuration
      • The difference between configureWebpack and chainWebpack
    • 10. CSS related configuration
    • 11、pages
    • 12. Others
  • 2. Optimization
    • 1. Optimize and package chunk-vendors.js
    • 2. Remove the printed information when packing
    • 3. Enable gizp compression
    • 4. Use vue-cli3 image compression [image-webpack-loader]
    • 5. Mobile terminal. px2rem response style
  • 3. Multi-page application development and configuration
    • build project
        1. create project
        1. Build file structure
        1. configure routing
        1. Configure vue.config.js
    • Precautions
    • Set page dynamic title
    • Routing submodule settings
  • 4. Complete code of vue.config.js

official document

In versions below vue-cli3, some configurations about webpack are in the config directory file, but in versions above vue-cli3, there is no config directory, so how to configure webpack?
3.x After initializing the project, there are no build and config files. If you want to configure webpack-related content, you need to create a vue.config.js file in the root directory (same level as package.json). Once this file exists , then it will be automatically loaded by @vue/cli-service. (But we need to manually create vue.config.js, which is at the same level as package.json)

1. Commonly used configurations in vue.config.js

Most of them are in the configuration (optional)

1. Export module

Routine operations still use the commjs syntax

module.exports = {

}

2. PublicPath is the basic Url for deploying the application package

The basic Url for deploying the application package, the default is /, which can be set to a relative path./, the package typed out in this way can be deployed to any path

let developmentPath='./';//开发环境-npm run serve时引用文件路径
let productionPath='./';//生产环境-npm run build打包后引用文件路径
module.exports = {
    publicPath: process.env.NODE_ENV === 'production' ? productionPath: developmentPath, // 基本路径-引用文件的路
}

3. outputDir output file directory

Output file directory (the directory generated after packaging, default dist)

module.exports = {
  outputDir: __dirname + '/server/dist', //build之后静态文件输出路径
  //outputDir: 'dist',
}

4. assetsDir static resource directory generated after packaging

The static resource directory generated after packaging, the default is " ", which is the location where our packaged css, js, etc. are stored

module.exports = {
 assetsDir: 'static',
}

5、lintOnSave

Whether to check when saving

module.exports = {
    lintOnSave: process.env.NODE_ENV !== 'production',// eslint-loader 
}

6. productionSourceMap The source map of the production environment

The source map of the production environment, which can be set to false to speed up the production environment build, the default value is true

module.exports = {
    productionSourceMap: false,
}

7、devServer

The front-end and back-end cross-domain problems can be solved through devServer.proxy (reverse proxy)

module.exports = {
// 反向代理
  devServer: {
    index: '/login.html',   //默认打开文件
    open: true,             //自动打开浏览器
    host: 'localhost',      //默认打开域名
    port: 8080,             //默认打开端口号
    https: false,           //开启关闭https请求
    hotOnly: false,         //热更

    proxy: {
      // 配置跨域
      '/api': {
        target: 'http://dev.aabb.cn:8082/', //代理地址,这里设置的地址会代替axios中设置的baseURL
        ws: true,    proxy websockets
        changeOrigin: true,// 如果接口跨域,需要进行这个参数配置
        pathRewrite: {                //pathRewrite方法重写url
          '^/api': '/',
        },
      },
    },
  },
} 

Extension: The difference between hot and hotOnly is that when some modules do not support hot update, the former will automatically refresh the page, while the latter will not refresh the page, but output hot update failure on the console

8. chainWebpack webpack configuration

module.exports = {
  chainWebpack: (config) => {
    config.plugins.delete('preload')
    config.plugins.delete('prefetch')

    config.module
      .rule('svg')
      .exclude.add(resolve('src/assets/icons'))
      .end()

    config.module
      .rule('icons')
      .test(/\.svg$/)
      .include.add(resolve('src/assets/icons'))
      .end()
      .use('svg-sprite-loader')
      .loader('svg-sprite-loader')
      .options({
        symbolId: 'icon-[name]',
      })
      .end()

    const imagesRule = config.module.rule('images')
    imagesRule.uses.clear() //清除原本的images loader配置
    imagesRule
      .test(/\.(jpg|gif|png|svg)$/)
      .exclude.add(path.join(__dirname, '../node_modules')) //不对node_modules里的图片转base64
      .end()
      .use('url-loader')
      .loader('url-loader')
      .options({ name: 'img/[name].[hash:8].[ext]', limit: 6000000 })

    config.optimization.splitChunks({
      cacheGroups: {

        vendors: {
          name: 'chunk-vendors',
          minChunks: pageNum,
          test: /node_modules/,
          priority: -10,
          chunks: 'initial',
        },

        elementUI: {
          name: 'chunk-elementUI', // split elementUI into a single package
          priority: 20, // the weight needs to be larger than libs and app or it will be packaged into libs or app
          test: /[\\/]node_modules[\\/]_?element-ui(.*)/, // in order to adapt to cnpm
        },

        commons: {
          name: 'chunk-commons',
          test: resolve('src/components'), // can customize your rules
          minChunks: 3, //  minimum common number
          priority: 5,
          reuseExistingChunk: true,
        },
      },
    })
  },
}

Extension:
Preload: Used to mark resources that will be used after the page is loaded, and the browser will load the preload markup file before the main body is rendered. The Vue CLI application will automatically generate preload hints for all files needed for initial rendering;

Prefetch: Used to mark the content that the browser preloads in idle time after the page load is complete. The Vue CLI app automatically generates prefetch hints for all JavaScript files generated as async chunks (the product of on-demand code splitting via dynamic import() ) by default.

9. configureWebpack webpack configuration

webpack configuration

const UglifyJsPlugin = require('uglifyjs-webpack-plugin')
const CompressionWebpackPlugin = require('compression-webpack-plugin')

const productionGzipExtensions = ['js', 'css']
const Version = 'V6.1'
const Timestamp = new Date().getTime()

module.exports = {
    webpack配置
    configureWebpack: (config) => {
          // 为生产环境修改配置
        if (process.env.NODE_ENV === 'production') {
      
            config.plugins.push(
                new UglifyJsPlugin({
                    uglifyOptions: {
                        compress: {
                            drop_debugger: true,//生产环境自动删除debugger
                            drop_console: true, //生产环境自动删除console
                        },
                        warnings: false,
                    },
                    sourceMap: false,   //关掉sourcemap 会生成对于调试的完整的.map文件,但同时也会减慢打包速度
                    parallel: true, //使用多进程并行运行来提高构建速度。默认并发运行数:os.cpus().length - 1。
                }),


                new CompressionWebpackPlugin({
                    filename: '[path].gz[query]',
                    algorithm: 'gzip',
                    test: new RegExp('\\.(' + productionGzipExtensions.join('|') + ')$'),
                    threshold: 10240,
                    minRatio: 0.8,
                })
            )
        }

        // 在这里配置后,减少了压缩的包内容,需要在public/index.html通过cdn方式再引入,注意对应的版本
        config.externals = { 
            vue: 'Vue',
            'vue-router': 'VueRouter',
            vuex: 'Vuex',
            axios: 'axios',
            jquery: '$',
            moment: 'moment',
            'mint-ui': 'MINT'
        },


         // 别名配置
        Object.assign(config, {
            // 开发生产共同配置
            resolve: {
                alias: {
                '@': path.resolve(__dirname, './src'),
                '@c': path.resolve(__dirname, './src/components'),
                '@p': path.resolve(__dirname, './src/pages')
                }
            }
        }),

        config.output.filename = `[name].${Version}.${Timestamp}.js`  //打包生成的文件
        config.output.chunkFilename = `[name].${Version}.${Timestamp}.js`
    },
 }

extension:

  1. UglifyJS Webpack:
    Plugin is used to minify (compress and optimize) js files, at least Node v6.9.0 and Webpack v4.0.0 are required.
  2. compression-webpack-plugin
    Vue configures compression-webpack-plugin to achieve Gzip compression
  3. The chunkFilename
    and webpack.optimize.CommonsChunkPlugin plug-ins have similar functions, both are used to extract common modules, but the usage is different
entry:{
    main:__dirname + '/app/main.js',
    index:__dirname + '/app/index.js'      
},
output:{
    path:__dirname + '/public', //通过HtmlWebpackPlugin插件生成的html文件存放在这个目录下面
    filename:'/js/[name].js', //编译生成的js文件存放到根目录下面的js目录下面,如果js目录不存在则自动创建
    /*
     * chunkFilename用来打包require.ensure方法中引入的模块,如果该方法中没有引入任何模块则不会生成任何chunk块文件
     * 比如在main.js文件中,require.ensure([],function(require){alert(11);}),这样不会打包块文件
     * 只有这样才会打包生成块文件require.ensure([],function(require){alert(11);require('./greeter')})
     * 或者这样require.ensure(['./greeter'],function(require){alert(11);})
     * chunk的hash值只有在require.ensure中引入的模块发生变化,hash值才会改变
     * 注意:对于不是在ensure方法中引入的模块,此属性不会生效,只能用CommonsChunkPlugin插件来提取
     * */
    chunkFilename:'js/[chunkhash:8].chunk.js'
},

The difference between configureWebpack and chainWebpack

Here configureWebpack and chainWebpack have the same function, the only difference is that they modify the webpack configuration in different ways:

  1. chainWebpack modifies the default webpack configuration through chain programming
  2. configureWebpack modifies the default webpack configuration by manipulating objects.
    If the modified configuration for a loader or plugin is one item, chainWebpack is recommended. If there are multiple items, use configureWebpack to overwrite it directly.

10. CSS related configuration

Here, the global sass needs to be installed to depend on sass-loader less-loader

 css: {
        loaderOptions: {
            scss: {
                additionalData: `@import "@/assets/css/reset.scss";@import "@/assets/css/globle.scss";`  //注意配置的键名
            },
            postcss: {
                plugins: [
                    //remUnit这个配置项的数值是多少呢??? 通常我们是根据设计图来定这个值,原因很简单,便于开发。
                    //假如设计图给的宽度是750,我们通常就会把remUnit设置为75,这样我们写样式时,可以直接按照设计图标注的宽高来1:1还原开发。
                    require('postcss-px2rem')({
                        remUnit: 37.5
                    })
                ]
            }
        }
    },

Due to different versions of sass-loader, the key name of additionalData in loaderOptions is also different

  • sass-loader loader v8-, the option name is "data",
  • In sass-loader loader v8, the option name is "prependData",
  • sass-loader loader v10+, the option name is "additionalData",

11、pages

Related parameters of webpack and vue multi-page application development in vue-cli3
:

  • entry: the entry of the page
  • template: template source
  • filename: output in dist/index.html
  • title: The title tag in the template needs to be
  • chunks: the chunks included in this page, by default it will include
module.exports = {
   pages:{
       main: {
           // page 的入口
           entry: "src/pages/main/main.js",
           // 模板来源
           template: "public/index.html",
           // 在 dist/index.html 的输出
           filename: "main.html",
           // 当使用 title 选项时,
           // template 中的 title 标签需要是 <title><%= htmlWebpackPlugin.options.title %></title>
           title: "Index Page",
           // 在这个页面中包含的块,默认情况下会包含
           // 提取出来的通用 chunk 和 vendor chunk。
           chunks: ["chunk-vendors", "chunk-common", "main"]
       },
       hh: {
           // page 的入口
           entry: "src/pages/login/main.js",
           // 模板来源
           template: "public/index.html",
           // 在 dist/index.html 的输出
           filename: "login.html",
           // 当使用 title 选项时,
           // template 中的 title 标签需要是 <title><%= htmlWebpackPlugin.options.title %></title>
           title: "Index Page",
           // 在这个页面中包含的块,默认情况下会包含
           // 提取出来的通用 chunk 和 vendor chunk。
           chunks: ["chunk-vendors", "chunk-common", "hh"]
       },
       // 当使用只有入口的字符串格式时,
       // 模板会被推导为 `public/subpage.html`
       // 并且如果找不到的话,就回退到 `public/index.html`。
       // 输出文件名会被推导为 `subpage.html`。
       subpage: "src/subpage/main.js"
   },
}

encapsulation

const glob = require('glob') // 引入glob模块,用于扫描全部src/pages/**/main.js(返回的是一个数组)
// 打包多入口文件基本配置
function getPagesInfo() {
    let pages = {}

    glob.sync('src/pages/**/main.js').forEach((entry, i) => {
        let name = entry.slice(10, -8)
        pages[name] = {
            entry: entry,
            template: 'public.index.html',
            filename: name + '.html',
            title: '',
            chunks: ["chunk-vendors", "chunk-common", name]
        }
    })
    return pages
}
module.exports = {
    pages: getPagesInfo(),
    publicPath: './kk',
    assetsDir: 'static',
};

12. Others

  • parallel: require('os').cpus().length > 1, // Whether to use thread-loader for Babel or TypeScript. This option is automatically enabled when the system's CPU has more than one core and only works for production builds.
  • pwa: {}, // PWA plug-in related configuration
  • pluginOptions: {} // third-party plugin configuration

Very good pwa plug-in related configuration
pwa introduction and use

2. Optimization

1. Optimize and package chunk-vendors.js

When running the project and packaging it, you will find that the chunk-vendors.js file is very large, because webpack compresses all dependencies into this file, then we can split it and package all dependencies into a separate js;

/*
利用splitChunks将每个依赖包单独打包,在生产环境下配置,代码如下
*/

configureWebpack: (config) => {
    if (process.env.NODE_ENV === 'production') {
      // 为生产环境修改配置...
      config.mode = 'production'
      // 将每个依赖包打包成单独的js文件
      let optimization = {
        runtimeChunk: 'single',
        splitChunks: {
          chunks: 'all',
          maxInitialRequests: Infinity,
          minSize: 20000, // 依赖包超过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 `npm.${packageName.replace('@', '')}`
              }
            }
          }
        }
      }
      Object.assign(config, {
        optimization
      })
    } 
  }

2. Remove the printed information when packing

As mentioned above, the operation of printing in the past (console, debug) will be explained in detail here

  1. First download the related plugin uglifyjs-webpack-plugin

    npm i -D uglifyjs-webpack-plugin

  2. Introduce it in the vue.config.js file, and add the following code in the optimization of configureWebpack

const UglifyPlugin = require('uglifyjs-webpack-plugin')
module.exports = {
    
 configureWebpack: (config) => {
    if (process.env.NODE_ENV === 'production') {
      // 为生产环境修改配置...
      config.mode = 'production'
      // 将每个依赖包打包成单独的js文件
      let optimization = {

        /*以下代码适用于uglifyjs-webpack-plugin 2.1.1及以前的版本*/
        minimizer: [new UglifyPlugin({
          uglifyOptions: {
            compress: {
              warnings: false,
              drop_console: true, // console
              drop_debugger: false,
              pure_funcs: ['console.log'] // 移除console
            }
          }
        })]
        
      }
      Object.assign(config, {
        optimization
      })
    }
   
  }
}

The new version of uglifyjs-webpack-plugin needs to be written in the following way

minimizer: [new UglifyPlugin({
    uglifyOptions: {
        warnings: false,
        compress: {
            drop_console: false, // console
            drop_debugger: false,
            pure_funcs: ['console.log'] // 移除console
        }
    }
})]

3. Enable gizp compression

Gizp compression is an HTTP request optimization method that improves loading speed by reducing file size. HTML, js, css files and even json data can be compressed with it, which can reduce the volume by more than 60%. Webpack can use the compression webpack plugin to achieve gzip compression when packaging.

  1. Download the compression webpack plugin

    npm i -D compression-webpack-plugin

  2. vue.config.js configuration

const CompressionPlugin = require("compression-webpack-plugin");
module.exports = {

  configureWebpack: (config) => {
    if (process.env.NODE_ENV === 'production') {
      // 为生产环境修改配置...
      config.mode = 'production';

      if(openGzip){
        config.plugins = [
          ...config.plugins,
          new CompressionPlugin({
            test:/\.js$|\.html$|.\css/, //匹配文件名
            threshold: 10240,//对超过10k的数据压缩
            deleteOriginalAssets: false //不删除源文件
          })
        ]
      }

    } else {
      // 为开发环境修改配置...
      config.mode = 'development';
    }
    
  }
}
  1. package.js configuration
{
  "name": "demo-cli3",
  "version": "1.0.0",
  "openGizp": false,
  ...
}

4. Use vue-cli3 image compression [image-webpack-loader]

  1. Download image-webpack-loader

    npm install --save-dev image-webpack-loader

  2. Modify the relevant configuration in vue.config.js.
    The 4M image is compressed to 1.4M with the default settings, and the custom settings can be smaller

module.exports = {
  ...
  // 默认设置
  const defaultOptions = {
      bypassOnDebug: true
  }
 //  自定义设置
  const customOptions = {
      mozjpeg: {
        progressive: true,
        quality: 50
      },
      optipng: {
        enabled: true,
      },
      pngquant: {
        quality: [0.5, 0.65],
        speed: 4
      },
      gifsicle: {
        interlaced: false,
      },
      // 不支持WEBP就不要写这一项
      webp: {
        quality: 75
      }
  }
  chainWebpack: config => {

    config.module.rule('images') 
        .test(/\.(gif|png|jpe?g|svg)$/i)
        .use('image-webpack-loader')
        .loader('image-webpack-loader')
        .options(customOptions)
        .end() 

  }
}

5. Mobile terminal. px2rem response style

  1. Install

npm i -S lib-flexible postcss-px2rem

  1. Introduce lib-flexible

Introduce lib-flexible in main.js in the project entry

import 'lib-flexible' 

# 注意事项: 由于flexible会动态给页面header中添加<meta name='viewport' >标签,所以务必请把目录 public/index.html 中的这个标签删除!!
  1. Configure postcss-px2rem

The following configuration is performed in vue.config.js in the project

module.exports = { 
    css: {
        loaderOptions: { 
            css: {}, 
            postcss: { 
                plugins: [ require('postcss-px2rem')({ remUnit: 37.5 }) 
                ] 
            } 
        } 
    } 
}

3. Multi-page application development and configuration

build project

1. Create a project

Same as our normal project creation, here we create it through vue-cli3 scaffolding

Vue create project name
select the dependencies you need and proceed to the next step

2. Build the file structure

  • Create new pages to store the relevant content of each page
  • pages---Create related pages to store files
  • Put main.js and router.js in the page file

3. Configure routing

import Vue from 'vue'
import VueRouter from 'vue-router'
Vue.use(VueRouter)

// const originalPush = VueRouter.prototype.push
// VueRouter.prototype.push = function push(location) {
//   return originalPush.call(this, location).catch((err) => err)
// }
const routes = [
    {
        path: '/login',
        name: 'login',
        component: () => import('./views/index.vue'),
        // component:()=>import('./reset.vue'),
        meta: {
            title: '这里是动态title'
        },
        children: [

            /*  
            单页面应用的写法     
            {
                path: 'reset',
                name: 'reset',
                component: () => import('./reset.vue')
            
            },
            */
           
            //  ***多页面的写法
            {
                path: 'editJobs',
                components: {
                    'editJobs': () => import('./views/reset.vue'),
                },
            },],

    },
    // {
    //     path: '/',
    //     redirect: '/'
    // }

]
export default new VueRouter({
    mode: 'hash',
    base: process.env.BASE_URL,
    routes
})

4. Configure vue.config.js

// 打包多入口文件基本配置
function getPagesInfo() {
    let pages = {}
    const glob = require('glob') // 引入glob模块,用于扫描全部src/pages/**/main.js(返回的是一个数组)
    glob.sync('src/pages/**/main.js').forEach((entry, i) => {
        let name = entry.slice(10, -8)
        pages[name] = {
            entry: entry,
            template: 'public.index.html',
            filename: name + '.html',
            title: '',
            chunks: ["chunk-vendors", "chunk-common", name]
        }
    })
    return pages
}
module.exports = {
    pages: getPagesInfo(),
    publicPath: './kk',
    assetsDir: 'static',
};

Precautions

Set page dynamic title

  1. Download vue-wechat-title

npm i -S vue-wechat-title

  1. Global import in main.js
import VueWechatTitle from 'vue-wechat-title'
Vue.use(VueWechatTitle)
  1. Set in App.vue
<template>
<!-- 动态设置title -->
  <div id="app" v-wechat-title='$route.meta.title'>
    <router-view/>
  </div>
</template>

Routing submodule settings

  1. Routing configuration method
const routes = [
    {
        path: '/login',
        name: 'login',
        component: () => import('./views/index.vue'),
        meta: {
            title: '这里是动态title'
        },
        children: [
           
            //  ***多页面的写法
            {
                path: 'editJobs',
                components: {
                    'editJobs': () => import('./views/reset.vue'),
                },
            },],

    },
]
  1. Rendering on the page
<template>
  <div>
    login
    <router-link :to="{ name: 'reset' }" tag="li">我的收藏</router-link>
    这里的name对应的是route配置里的名字(别忘了地址连里面的path)
    <router-view name="editJobs">待完善信息</router-view>
  </div>
</template>

4. Complete code of vue.config.js

// 打包多入口文件基本配置
let developmentPath = './';//开发环境-npm run serve时引用文件路径
let productionPath = './';//生产环境-npm run build打包后引用文件路径

const UglifyJsPlugin = require('uglifyjs-webpack-plugin')//生产环境取消打印
const CompressionWebpackPlugin = require('compression-webpack-plugin')//gzip压缩

const productionGzipExtensions = ['js', 'css']
const Version = 'V6.1'
const Timestamp = new Date().getTime()
function getPagesInfo() {
    let pages = {}
    const glob = require('glob') // 引入glob模块,用于扫描全部src/pages/**/main.js(返回的是一个数组)
    glob.sync('src/pages/**/main.js').forEach((entry, i) => {
        let name = entry.slice(10, -8)
        pages[name] = {
            entry: entry,
            template: 'public.index.html',
            filename: name + '.html',
            title: '',
            chunks: ["chunk-vendors", "chunk-common", name]
        }
    })
    return pages
}
// 打包相关
module.exports = {
    pages: getPagesInfo(),//多页面应用配置
    publicPath: process.env.NODE_ENV === 'production' ? productionPath : developmentPath, // 基本路径-引用文件的路 __dirname + '/server/dist', //build之后静态文件输出路径
    assetsDir: 'static',//静态资源大包位置
    outputDir: __dirname + '/server/dist', //build之后静态文件输出路径
    lintOnSave: process.env.NODE_ENV !== 'production',// 打包的时候eslint-loader检查 
    productionSourceMap: false,//source map 检查
    // 启动服务器
    devServer: {
        index: '/login.html',   //默认打开文件
        open: true,             //自动打开浏览器
        host: 'localhost',      //默认打开域名
        port: 8080,             //默认打开端口号
        https: false,           //开启关闭https请求
        hotOnly: false,         //热更
        // 反向代理
        proxy: {
            // 配置跨域
            '/api': {
                target: 'http://dev.aabb.cn:8082/', //代理地址,这里设置的地址会代替axios中设置的baseURL
                ws: true,    proxy websockets
                changeOrigin: true,// 如果接口跨域,需要进行这个参数配置
                pathRewrite: {                //pathRewrite方法重写url
                    '^/api': '/',
                },
            },
        },
    },
    // webpack配置  链式
    chainWebpack: (config) => {
        // 1、取消预加载增加加载速度
        config.plugins.delete('preload')
        config.plugins.delete('prefetch')

        // 2、vue中使用SVG图标,并且想批量导入,然后需要使用的时候直接添加就可以
        config.module
            .rule('svg')
            .exclude.add(resolve('src/assets/icons'))
            .end()
        config.module
            .rule('icons')
            .test(/\.svg$/)
            .include.add(resolve('src/assets/icons'))
            .end()
            .use('svg-sprite-loader')
            .loader('svg-sprite-loader')
            .options({
                symbolId: 'icon-[name]',
            })
            .end()

        // 3、图片处理
        const imagesRule = config.module.rule('images')
        imagesRule.uses.clear() //清除原本的images loader配置
        imagesRule
            .test(/\.(jpg|gif|png|svg)$/)
            .exclude.add(path.join(__dirname, '../node_modules')) //不对node_modules里的图片转base64
            .end()
            .use('url-loader')
            .loader('url-loader')
            .options({ name: 'img/[name].[hash:8].[ext]', limit: 6000000 })

        config.optimization.splitChunks({
            cacheGroups: {

                vendors: {
                    name: 'chunk-vendors',
                    minChunks: pageNum,
                    test: /node_modules/,
                    priority: -10,
                    chunks: 'initial',
                },

                elementUI: {
                    name: 'chunk-elementUI', // split elementUI into a single package
                    priority: 20, // the weight needs to be larger than libs and app or it will be packaged into libs or app
                    test: /[\\/]node_modules[\\/]_?element-ui(.*)/, // in order to adapt to cnpm
                },

                commons: {
                    name: 'chunk-commons',
                    test: resolve('src/components'), // can customize your rules
                    minChunks: 3, //  minimum common number
                    priority: 5,
                    reuseExistingChunk: true,
                },
            },
        })
    },
    // webpack配置
    configureWebpack: (config) => {
          // 为生产环境修改配置
        if (process.env.NODE_ENV === 'production') {
      
            config.plugins.push(
                  // 1、取消打印
                new UglifyJsPlugin({
                    uglifyOptions: {
                        compress: {
                            drop_debugger: true,//生产环境自动删除debugger
                            drop_console: true, //生产环境自动删除console
                        },
                        warnings: false,
                    },
                    sourceMap: false,   //关掉sourcemap 会生成对于调试的完整的.map文件,但同时也会减慢打包速度
                    parallel: true, //使用多进程并行运行来提高构建速度。默认并发运行数:os.cpus().length - 1。
                }),

                // 2、gzip压缩
                new CompressionWebpackPlugin({
                    filename: '[path].gz[query]',
                    algorithm: 'gzip',
                    test: new RegExp('\\.(' + productionGzipExtensions.join('|') + ')$'),
                    threshold: 10240,
                    minRatio: 0.8,
                })
            )
        }

        // 在这里配置后,减少了压缩的包内容,需要在public/index.html通过cdn方式再引入,注意对应的版本
        config.externals = { 
            vue: 'Vue',
            'vue-router': 'VueRouter',
            vuex: 'Vuex',
            axios: 'axios',
            jquery: '$',
            moment: 'moment',
            'mint-ui': 'MINT'
        },


         // 别名配置
        Object.assign(config, {
            // 开发生产共同配置
            resolve: {
                alias: {
                '@': path.resolve(__dirname, './src'),
                '@c': path.resolve(__dirname, './src/components'),
                '@p': path.resolve(__dirname, './src/pages')
                }
            }
        }),

        config.output.filename = `[name].${Version}.${Timestamp}.js`  //打包生成的文件
        config.output.chunkFilename = `[name].${Version}.${Timestamp}.js`
    },
    // css相关
    css: {
        loaderOptions: {
            // 配置全局sass
            scss: {
                additionalData: `@import "@/assets/css/reset.scss";@import "@/assets/css/globle.scss";`  //注意配置的键名
            },
            // lib-flexible
            postcss: {
                plugins: [
                    //remUnit这个配置项的数值是多少呢??? 通常我们是根据设计图来定这个值,原因很简单,便于开发。
                    //假如设计图给的宽度是750,我们通常就会把remUnit设置为75,这样我们写样式时,可以直接按照设计图标注的宽高来1:1还原开发。
                    require('postcss-px2rem')({
                        remUnit: 37.5
                    })
                ]
            }
        }
    },
    parallel: require('os').cpus().length > 1, // 是否为 Babel 或 TypeScript 使用 thread-loader。该选项在系统的 CPU 有多于一个内核时自动启用,仅作用于生产构建。
    pwa: {}, // PWA 插件相关配置 
    pluginOptions: {},  // 第三方插件配置
};

Guess you like

Origin blog.csdn.net/gcyaozuodashen/article/details/128217703