webpack 是一个模块打包工具(前提要安装 node使用npm来安装webpack)
注意npm在安装的时候速度很慢,建议用淘宝镜像
//第一安装淘宝 npm install -g cnpm --registry=https://registry.npm.taobao.org
//或者使用–registry参数指定镜像服务器地址,为了避免每次安装都需要--registry参数,可以使用如下命令进行永久设置: npm config set registry http://registry.npm.taobao.org
1、安装webpack,webpack-cli , webpack-dev-server
//全局安装 npm i webpack webpack-cli webpack-dev-server -g //查看webpack的信息 //webpack -v //局部安装 npm i webpack webpack-cli webpack-dev-server --save-d //查看webpack的信息 //npx webpack -v
2、webpack 的配置
添加webpack默认配置文件 webpack.config.js
//注意:这个文件名必须叫webpack.config.js如果需要改成别的名字,那么要用 npx webpack --config webpackconfig.js 这样就把配置文件改成webpackconfig.js了 //注意:在运行npx webpack命令时,webpack.config.js必须在当前目录下 const path = require('path'); module.exports = { //注意:这里是exports entry: { //打包的入口文件,即从哪个Js文件开始进行打包,这边是从src文件夹的index.js文件 'index': './src/index.js', //把./src/index.js路径下的文件打包成index.js 'main': './src/main.js' //把./src/main.js路径下的文件打包成main.js }, output: { // publicPath: 'https://www.cdn.cn', //表示把js文件全部放到指定的域名下,在引用的时候在添加上地址为前缀 filename: '[name].js', //打包好的文件命名
chunkFilename: '[name].chunk.js', //表示在入口文件中引用的文件打包到指定的文件名下,即间接加载的js文件 path: path.resolve(__dirname, 'dist') //这里的路径要用绝对路径,引入path模块,即文件放在dist文件夹下 },
resolve: {
extensions: ['.js', '.ts', '.tsx'] //表示书写的时候自动省略后缀,读取的时候自动获取,尽量在ts情况下应用, ts环境下需要配置
},
mode: 'development', // 这个工具是对js文件产生映射关系,方便排错 // inline表示生成的映射代码放到打包好的js文件中,如果没有,则另外产生一个映射文件 // cheap 表示不提示很祥细的错误位置,并且只检查业务代码 // module表示不仅对业务代码产生映射,还在loader和第三方库产生映射 // eval是应用js里的eval语法产生映射关系 // 最佳配置推荐:development => cheap-module-eval-source-map production => cheap-module-source-map devtool: 'cheap-module-eval-source-map', }
3、文件目录下的package.json配置(注意:json文件里是不允许注释的)
{ "name": "wp", "version": "1.0.0", "description": "", "private": true, //私有项目添加private声明 // "main": "index.js", //如果是私有的项目,可以关闭掉main的配置 "scripts": { "bundle": "webpack" //当在命令行里执行npm run bundle,那么系统自动从依赖里找webpack,并且执行npx webpack,那么这里就不用执行npx webpack了 }, "keywords": [], "author": "", "license": "ISC", "devDependencies": { "webpack": "^4.30.0", "webpack-cli": "^3.3.1", "webpack-dev-server": "^3.3.1" } }
4、loader的用法
loader 是模块打包工具,原本webpack是不提供如图片,文件等资源的打包,那么这时便可以引入模块打包工具,当在打包过程中,遇到不能打包的文件时,webpack就会引用相应的模块进行打包
//注意:这个文件名必须叫webpack.config.js如果需要改成别的名字,那么要用 npx webpack --config webpackconfig.js 这样就把配置文件改成webpackconfig.js了 //注意:在运行npx webpack命令时,webpack.config.js必须在当前目录下 const path = require('path'); module.exports = { //注意:这里是exports entry: './src/index.js', //打包的入口文件,即从哪个Js文件开始进行打包,这边是从src文件夹的index.js文件 output: { filename: 'test.js', //打包好的文件命名 path: path.resolve(__dirname, 'dist'), //这里的路径要用绝对路径,引入path模块,即文件放在dist文件夹下 }, mode: 'development', //当为production时会压缩代码,当为development时就不会压缩代码,默认是production module: { //webpack的模块打包工具 rules: [ //相应模块的打包规则 { test: /.(png|jpg|gif)$/, //较验规则,以正则表达式来较验 use: { loader: 'file-loader' //调用的模块,首先要先安装file-loader eg: npm i file-loader -D; } } ] } }
举例:对应的js入口
import Img from '../assets/img/baidu.png' console.log(Img); // 会输出转义好的img图片 b15c113aeddbeb606d938010b88cf8e6.png let pic = document.createElement('img'); pic.src = Img; let elem = document.createElement('div'); elem.appendChild(pic); document.body.appendChild(elem);
file-loader 模块,以下代码是放在rules的数组里面,font文件也可以用file-loader来打包
{ test: /.(png|jpg|gif)$/, //较验规则,以正则表达式来较验 use: { loader: 'file-loader', //调用的模块,首先要先安装file-loader eg: npm i file-loader -D; options: { //进行配置 name: '[name].[ext]', //注意:这里的内容要放在单引号里面,可以是[name],[hash],[path],后缀是[ext],更多祥见官网 // name: function(addr){ //这里可以是一个函数,接收一个地址的参数 // return 'abc.[name].[ext]'; // } outputPath: './image' //如果配置了outputPath那么就表示输出的路径在dist目录下的image文件夹下 } } }
url-loader模块,以下代码是放在rules的数组里面
// 这个插件会把文件转换成base64的代码,放在js文件里面,但是如果文件过大,那么会导致加载比较慢,建议只有小文件用这个loader { test: /.(png|jpg|gif)$/, //较验规则,以正则表达式来较验 use: { loader: 'url-loader', //调用的模块,首先要先安装url-loader eg: npm i url-loader -D; options: { //进行配置 name: '[name].[ext]', //注意:这里的内容要放在单引号里面,可以是[name],[hash],[path],后缀是[ext],更多祥见官网 // name: function(addr){ //这里可以是一个函数,接收一个地址的参数 // return 'abc.[name].[ext]'; // } outputPath: './image', //如果配置了outputPath那么就表示输出的路径在dist目录下的image文件夹下 limit: 2048 //表示当图片或者文件只有2Kb的时候转成base64,否则就会像file-loader一样工作 } } }
style-loader,css-loader模块的使用
{ test:/.css$/, //表示当遇到css文件的时候的处理方式 use: [ //use这时是以一个数组的形式应用,运行方式是从左到右,从下到上的,先运行css-loader再到style-loader 'style-loader', { loader: 'css-loader', options: { // importLoaders: 2, //表示在 css-loader 前应用的 loader 的数量,那么当sass中还有import的css样式时,那么同时也会走sass-loader和postcss-loader,如果没有sass-loader的时候可以不配置 modules: true //是否对css文件进行模块化管理,注意这里是modules } }, // 'sass-loader', //首先要安装sass-loader npm i sass-loader -D 前提要安装好style-loader 与 sass-loader 'postcss-loader' ] }
所对应的Js文件
import Img from '../assets/img/baidu.png'; import createElement from './createElement'; import style from './index.css'; createElement(); let pic = document.createElement('img'); pic.src = Img; pic.classList.add(style.set); //注意:如果是通用的标签,那么会作用于所有的对应元素,也可以用style['set'] pic.id = style.set; //如果要用里面的Id选择器,那么如右设置,那么id也会转成转码后的id let elem = document.createElement('div'); elem.appendChild(pic); document.body.appendChild(elem);
如果css是用sass来编写的,那么要添加sass-loader模块
{ test:/.sass$/, //如果css是用sass来编写的,那么要改变规则 use: [ 'style-loader', { loader: 'css-loader', options: { importLoaders: 2 //表示在 css-loader 前应用的 loader 的数量,那么当sass中还有import的css样式时,那么同时也会走sass-loader和postcss-loader } }, 'sass-loader', //首先要安装sass-loader npm i sass-loader -D 前提要安装好style-loader 与 sass-loader 'postcss-loader' ] }
postcss-loader模块,这个模块是用来给特定的样式添加产商前缀如-webkit-
首先添加postcss-loader模块并且添加配置
{ test:/.css/, //普通的css规则 use: ['style-loader', 'css-loader', 'postcss-loader'] //首先postcss-loader npm i postcss-loader -D }
添加一个配置文件postcss.config.js
module.exports = { plugins: [ require('autoprefixer') //首先要安装autoprefixer插件 npm i autoprefixer -D ] }
重新编译完后,就自动添加上产商的前缀了
5、plugins插件的应用
plugins 相当于webpack在生命周期函数里的某个期间运行的函数
html-webpack-plugin插件
new htmlWebpackPlugin({ title: 'index文件的标题', //输出的html的title设置 filename: 'index.html', //输出的html的文件名 template: './src/index.html', //引入template,这个可以指定一个html模板 showErrors: true, //当webpack报错的时候,会把错误信息包裹再一个pre中,默认是true。 // inject有四个值: true body head false // true =》 默认值,script标签位于html文件的 body 底部 // body =》 script标签位于html文件的 body 底部 // head =》 script标签位于html文件的 head中 // false =》 不插入生成的js文件,这个几乎不会用到的 inject: 'body', chunks: ['index'], //chunks主要用于多入口文件,当你有多个入口文件,那么数组里的值便是你需要选择打包进行的js文件包,如果不设置,则是全部显示 // excludeChunks: ['devor.js'], //排除掉一些js后全部打包 favicon: './assets/img/baidu.png', //给你生成的html文件生成一个 favicon ,值是一个路径 hash: true, //是否生成hash添加在引入文件地址的末尾,类似于我们常用的时间戳,比如最终引入是:<script type="text/javascript" src="bundle.049424f7d7ea5fa50656.js?049424f7d7ea5fa50656"></script>。这个可以避免缓存带来的麻烦 cache: true, //默认是true的,表示内容变化的时候生成一个新的文件 minify:{ caseSensitive: false, //是否大小写敏感 removeComments:true, // 去除注释 removeEmptyAttributes:true, // 去除空属性 collapseWhitespace: true //是否去除空格 } })
所对应的html的文件
<!DOCTYPE html> <html> <head> <meta charset="utf-8"/> <title><%= htmlWebpackPlugin.options.title %></title> </head> <body> </body> </html>
clean-webpack-plugin插件
plugins: [ new cleanWebpackPlugin({ //首先要安装clean-webpack-plugin,并且引入const {CleanWebpackPlugin} = require('clean-webpack-plugin'); cleanOnceBeforeBuildPatterns: ['./dist'] //这个插件的主要作用是清除上次打包的文件 该配置表示,清除上次建立的dist文件夹下的所有内容 }) ]
6、webpack-dev-server的使用
--watch的妙用
在package里面做中上配置,那么当有文件修改的时候就会自动重新打包
利用webpack-dev-server 进行自动化打包
首先安装 webpack-dev-server 利用命令行 npm i webpack-dev-server -D
devServer: { //前提在安装了webpack-dev-server后使用 contentBase: './dist', //打包后的文件目录 open: true, //是否在运行npm run start后自动打开浏览器 port: 8090, //配置端口号 hot: true, //启用 webpack 的模块热替换特性: hotOnly: true, //替换失败后,是否重新刷新页面,一般与hot配置使用 proxy: { //在devServer服务器下进行反向代理 '/api': 'http://localhost:3000' } }
注意:如果配置了hot与hotOnly为true那么相对应的要开启webpack局部更新的插件
const webpack = require('webpack'); //要先引入webpack里的默认模块 //在Plugins里添加插件 plugins: [ new webpack.HotModuleReplacementPlugin() ]
在package.json做如下配置
"scripts": { "start": "webpack-dev-server" },
使用的时候用 npm run start 便可(注意:这个功能打包出来的dist文件是放面电脑内存中的,如果需要打包引出,那么需要运行另外webpack的命令)
7、webpack中使用Babel处理ES6语法
所需要准备的插件:参看 https://www.babeljs.cn/setup#installation
npm install --save-dev babel-loader @babel/core //建立加载器
npm install @babel/preset-env --save-dev //实现语法的转换
npm install --save @babel/polyfill //适配一些浏览器无法转换的ES6语法 注意使用这个要在入口文件顶部引入,如果配置usage,则无需引入,但需要安装 import "@babel/polyfill";
{ test: /.js$/, exclude: /node_modules/, use: { loader: "babel-loader", options: { presets: [["@babel/preset-env", {"useBuiltIns": 'usage'}]] } } }
以上是在modules里配置的
8、分离出生产模式与开发模式的配置
首先安装webpack-merge --save-d模块实现配置的拼装 , 新建build文件夹,并且添加配置, 并且在build里添加三个js文件,修改package.json里的配置如下,
在打包有过程中有可能会提示以下内容:
WARNING: We noticed you're using the `useBuiltIns` option without declaring a core-js version. Currently, we assume version 2.x when no version is passed. Since this default version will likely change in future versions of Babel, we recommend explicitly setting the core-js version you are using via the `corejs` option. You should also be sure that the version you pass to the `corejs` option matches the version specified in your `package.json`'s `dependencies` section. If it doesn't, you need to run one of the following commands: npm install --save core-js@2 npm install --save core-js@3 yarn add core-js@2 yarn add core-js@3
这个时候就需要安装 npm install --save core-js@2 同时还要在babel中做如下配置,具体见代码:
"scripts": { "start": "webpack-dev-server --config ./build/webpack.dev.js", "build": "webpack --config ./build/webpack.pro.js" },
webpack.dev.js的内容如下
let path = require('path'); let commonConfig = require('./webpack.common'); let merge = require('webpack-merge'); let devConfig = { mode: 'development', devtool: 'cheap-module-eval-source-map', devServer: { contentBase: path.resolve('./', 'dist'), port: 8090, open: true } }; module.exports = merge(commonConfig, devConfig);
webpack.common.js的内容如下:(注意:不要配置resolve: extensions)
let path = require('path'); let HtmlWebpackPlugin = require('html-webpack-plugin'); let {CleanWebpackPlugin} = require('clean-webpack-plugin'); module.exports = { entry: { index: path.resolve('./', 'src/index.js') }, output: { filename: '[name].js', path: path.resolve('./', 'dist') }, module: { rules: [ { test: /.css$/, exclude: /node_modules/, use: [ 'style-loader', { loader: 'css-loader', options: { modules: true } } ] }, { test: /.js$/, exclude: /node_modules/, use: { loader: 'babel-loader', options: { presets: [["@babel/preset-env", { "useBuiltIns": 'usage', "corejs": 2 //对应上面的core.js的配置 }]] } } } ] }, plugins: [ new HtmlWebpackPlugin({ template: path.resolve('./', 'src/temp/index.html'), filename: 'index.html', hash: true, minify:{ caseSensitive: false, //是否大小写敏感 removeComments:true, // 去除注释 removeEmptyAttributes:true, // 去除空属性 collapseWhitespace: true //是否去除空格 } }), new CleanWebpackPlugin({ cleanOnceBeforeBuildPatterns: [path.resolve('./', 'dist')] }) ] };
webpack.pro.js的内容如下
let merge = require('webpack-merge'); let commonConfig = require('./webpack.common'); let proConfig = { mode: 'production', devtool: 'cheap-module-source-map', }; module.exports = merge(commonConfig, proConfig);
9、webpack 中的 code-spliting(代码分割)
添加配置如下:
optimization: { splitChunks: { chunks: "all" } },
代码分割与webpack无关,只是为了让网页响应速度更快
其实webpack底层应用了SplitChunksPlugin插件对代码进行分割(常用配置如下):
optimization: { //默认配置如下: splitChunks: { chunks: "async", //async: 对异歩加载的文件进行分割,all对全部文件,initial对同步代码做分割 minSize: 30000, //开始化割的起点大小 这里的30000表示Bite maxSize: 0, //这个选项可配也可不配置,如果配置了,那么会对分割好的代码进行二次分割,通常不配置 minChunks: 1, //表示代码被调用了几次时进行代码分割 maxAsyncRequests: 5, //表示同时加载的类库是5个,如果多于5个的时候就不会进行代码分割了 maxInitialRequests: 3, //表示入口文件进行加载的时候,入口文件引入的库做代码分割最多只能分割出3个,多则不会进行分割了 automaticNameDelimiter: '~', //文件名连接符 name: true, //在cacheGroups里取的filename有效, 一般不会去更改这个配置 cacheGroups: { vendors: { test: /[\/]node_modules[\/]/, //判断第三方库是否是通过npm安装到node_modules下面,如果是则进行打包,打包生成的名字是vendor~name, 表示入口文件 priority: -10, //表示优先级,越是优先级越高在符合条件的情况下,就会被打包到对应的目录下 filename: 'vendors.js' //如果配置了该选项表示把所有的文件全部打包到vendors.js文件下 }, default: { //表示当打包条件满足的情况下,但是对应的js包又不在node_modules文件里面,那么就会走该配置 minChunks: 2, priority: -20, reuseExistingChunk: true, //表示已经被打包过了,那么就不再进行打包了 filename: 'common.js' //打包好的文件会旋转到common.js里面如果没有指定这个,则会生成default~name.js文件 } } } },
10、Lazy Loading 懒加载
实现懒加载可以利用ES7的async...await来实现,具体应用实例如下
//实现懒加载的方法可以利用ES7里的async... await来实现 let getMethod = async () => { let { default: _} = await import ('lodash'); console.log(_.add(2,3)); }; document.addEventListener('click', () => { getMethod(); }, false);
注意动态加载的这个方法,在IE9-IE11浏览器下会报错,暂未找到有效的解决办法,不过以上方法可以在谷歌浏览器下正常运行
11、CSS文件的代码分割
通常来讲,通过webpack来打包的css文件会被打包入js文件中,但是为了把js代码与css代码区别开,一般会把css文件和js文件进行分开打包, 这个时候就会用到MiniCssExtractPlugin这个插件来操作,并且从webpack4.0开始官方就推荐使用该插件
安装
npm i mini-css-extract-plugin --save-d
注意:这个插件是不支持热更新,也就是说,当进行了更改后,必需手动的去刷新页面来查看效果, 所以一般配置上线的时候才会进行配置
let MiniCssExtractPlugin = require('mini-css-extract-plugin'); let merge = require('webpack-merge'); let commonConfig = require('./webpack.common'); let proConfig = { mode: 'production', // devtool: 'cheap-module-source-map', module: { rules: [ { test: /.css$/, use: [ MiniCssExtractPlugin.loader, //在把包环境中把style-loader替换成这个loader 'css-loader' ] }, ] }, plugins: [ new MiniCssExtractPlugin({ filename: '[name].css', //引用的css文件的名称 chunkFilename: '[name].chunk.css', //在直接引用的css文件中间接引入的文件 ignoreOrder: false //禁用警告 }) ] }; module.exports = merge(commonConfig, proConfig);
注意:以上打包的css文件是没有进行压缩的,如果想要对css文件进行压缩,那么需要引入 optimize-css-assets-webpack-plugin这个插件
//安装 npm i optimize-css-assets-webpack-plugin --save-d
在production环境中:
let MiniCssExtractPlugin = require('mini-css-extract-plugin'); let OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin'); //引入css样式压缩插件 let merge = require('webpack-merge'); let commonConfig = require('./webpack.common'); let proConfig = { mode: 'production', // devtool: 'cheap-module-source-map', optimization: { minimizer: [new OptimizeCSSAssetsPlugin({})], //实现css样式压缩 }, module: { rules: [ { test: /.css$/, use: [ MiniCssExtractPlugin.loader, //在把包环境中把style-loader替换成这个loader 'css-loader' ] }, ] }, plugins: [ new MiniCssExtractPlugin({ filename: '[name].css', //引用的css文件的名称 chunkFilename: '[name].chunk.css', //在直接引用的css文件中间接引入的文件 ignoreOrder: false //禁用警告 }) ] }; module.exports = merge(commonConfig, proConfig);
12、webpack与浏览器缓存的关系
在线上环境,当浏览器访问一个页面的时候,会对页面的库文件等进行缓存,这样当页面的更新的时候,会导致浏览器那边没有变化 ,原因是浏览器用的是缓存的旧
的代码,为了解决这个问题,可以在production的模式下配置出口文件的hash值,这个hash值且必需和内容相关联的,即contenthash,具体如下
output: { filename: '[name].[contenthash].js', chunkFilename: "[name].[contenthash].chunk.js", }
13、webpack中不兼容老的版本之间引入的的依赖问题
在一些老版本的库中,会对一些公共的工具类产生依赖,但是程序一般不会到node_modules中去更改旧的库文件,这个时候就需要一个中间件,帮忙引入所依赖的库
具体配置如下:
let webpack = require('webpack'); //首先引入webpack这个方法 plugins: [ ... new webpack.ProvidePlugin({ $: 'jquery', //表示当出现$这个符号时,会自动引入Jquery这个包 yf: ['jquery', 'merge'] //表求当出现yf这个符号时,会自动引入jquery并且调用里面的merge这个方法 }) ]
注意:在模块中的this是指定object的,并非指向window,如果有需要的情况下,可以改变全部的this指向,这个时候就需要安装imports-loader这个模块并且添加到module中,如果有安装babel依赖,那么就可以放在其后面,具体语法 loader: 'imports-loader? this=>window';
14、环境变量的使用
环境变量即在使用webpack进行配置的时候可以定义一些全局变量,配置会根据在全局范围内配置的变量进行全局调用
比如在package.json中配置一个set变量
"scripts": { "test": "webpack --config ./build/webpack.dev.js", "start": "webpack-dev-server --env.set=areyouok --config ./build/webpack.dev.js", "build": "webpack --config ./build/webpack.pro.js" },
那么调用的时候
module.exports = env => { console.log(env.set); //在打包的时候就会输出这个值,如果没有设定值,默认就会是true return merge(commonConfig, devConfig); };
可以利用这个特性,在打包环境中配置一个变量,这样就可以根据变量的值的变化自动选择打包的环境,如下:
15、library 工具库打包的注意点
通常来讲如果打包工具库方便别人的调用,会在output那进行配置,需要添加的配置有:
externals: ['lodash'], //如果库有第三方依赖的情况下,假定以lodash为例,那么就可以把lodash排除在外,无需打包到库里,祥细配置见官网 output: { path: path.resolve('./', 'dist'), library: 'library', //添加这个配置后可以通过<script src ='library.js'></script>进行引入 libraryTarget: 'umd' //添加这个配置后可以通过import library from 'library', let library from 'library'进行引入 },
16、typescript配置
a、在作用typescript的时候必需安装typescript可以使用以下命令
npm i typescirpt --save-d
b、在搭建好webpack环境后安装ts-loader使用以下命令
npm i ts-loader --save-d
c、在项目中进行typescript的项目初始化 tsc --init生成tsconfig文件
在webpackconfig中添加配置
{ test: /.tsx?$/, use: 'ts-loader', exclude: /node_modules/ },
注意:在使用一些js的库时需要引入typescript版本的可能用以下方法
//查询 以jquery为例 npm view @types/jquery versions //安装 npm i @types/jquery --save-d
如果在webpack中使用typescript开发node,那么还需要在webpack中添加配置target: 'node', 同时修改配置如下图:
17、使用webpackDevServer进行请求打包
在开发环境中,为了更好的进行测试,就需要引入一些测试数据,但是正式代码中的ajax请求的地址一般不进行随便更改,这个时候就需要引入devServer中的proxy进行请求的代理
假如请求的代码如下
import axios from 'axios'; axios.get('/learn/test.php').then((res) => { console.log(res); }).catch(error => { console.log(error); });
那么在proxy中实际要转接是http://localhost:80/learn/test.php,那么可以做如下配置
devServer: { contentBase: path.resolve('./', 'dist'), port: 8090, open: true, proxy: { '/learn': 'http://localhost:80' } },
注意以上代码会进行一次拼接,即返回地址:'http://localhost:80/learn' 对get请求里的 '/learn' 进行替换即在开发环境中实际请求的是'http://localhost:80/learn/test.php'这个地址;
如果进行比较完整性的配置
devServer: { contentBase: path.resolve('./', 'dist'), port: 8090, open: true, proxy: { '/api': { target: 'http://localhost:80/', //想要请求的数据地址 pathRewrite:{ '^/api': '', //通常拼接后的数据地址是http://localhost:80/learn,如果想拼接为http://localhost:80即可做该替换 'header.json': 'data.json', //表示遇到header.json时转成请求data.json }, secure: false, //表示接受运行在 HTTPS 上,且使用了无效证书的后端服务器的数据 changeOrigin: true, //通常该选项会配置成true header: { //如果想要通过请求头携带验证信息,那么可以配置该参数 cookie: '123456' } } } },
如果想要进行多个配置,那么可以改成以下写法
devServer: { contentBase: path.resolve('./', 'dist'), port: 8090, open: true, proxy: [{ context: ['/learn'], target: 'http://localhost:80' }] },
20、在vue-cli3中可以进行简单的配置
let path = require('path') module.exports = { lintOnSave: false, publicPath: process.env.NODE_ENV === 'production' ? '/production-sub-path/' : '/', chainWebpack: config => { config.resolve.alias.set('@', path.resolve(__dirname, 'src')).set('_c', path.resolve(__dirname, 'src/components')) }, productionSourceMap: false }