vuecli3+webpack4优化实践(删除console.log和配置dllPlugin)

本文主要介绍如何在vuecli3生成的项目中,打包输出时删除console.log和使用dllplugin,并记录了配置过程中踩到的坑。 (本人水平有限~希望大家多多指出有误的地方)

一、生产环境中删除console.log

在开发代码中写的console.log,可以通过配置webpack4中的terser-webpack-plugin插件达成目的,compress参数配置如下:

module.exports = {optimization: {minimizer: [new TerserPlugin({terserOptions: {compress: {warnings: false,drop_console: true,drop_debugger: true,pure_funcs: ['console.log']},},}),],},
};
复制代码

而@vue/cli-service的配置源码也是使用了terser-webpack-plugin插件进行Tree Shaking,以下是@vue/cli-service/prod.js的源码

module.exports = (api, options) => {api.chainWebpack(webpackConfig => {if (process.env.NODE_ENV === 'production') {const isLegacyBundle = process.env.VUE_CLI_MODERN_MODE && !process.env.VUE_CLI_MODERN_BUILDconst getAssetPath = require('../util/getAssetPath')const filename = getAssetPath(options,`js/[name]${isLegacyBundle ? `-legacy` : ``}${options.filenameHashing ? '.[contenthash:8]' : ''}.js`)webpackConfig.mode('production').devtool(options.productionSourceMap ? 'source-map' : false).output.filename(filename).chunkFilename(filename)// keep module.id stable when vendor modules does not changewebpackConfig.plugin('hash-module-ids').use(require('webpack/lib/HashedModuleIdsPlugin'), [{hashDigest: 'hex'}])// disable optimization during tests to speed things upif (process.env.VUE_CLI_TEST) {webpackConfig.optimization.minimize(false)} else {const TerserPlugin = require('terser-webpack-plugin')const terserOptions = require('./terserOptions')webpackConfig.optimization.minimizer([new TerserPlugin(terserOptions(options))])}}})
}
复制代码

在 vue.config.js 中的 configureWebpack 选项提供一个对象会被 webpack-merge 合并入最终的 webpack 配置,因此vue-cli3构建的项目中只需要修改terserOptions即可,vue.config.js配置如下:

module.exports = {publicPath: '/',outputDir: 'dist',devServer: {port: 8080,https: false,hotOnly: true,disableHostCheck: true,open: true,},productionSourceMap: false, // 生产打包时不输出map文件,增加打包速度configureWebpack: config => {if (process.env.NODE_ENV === 'production') {config.optimization.minimizer[0].options.terserOptions.compress.warnings = falseconfig.optimization.minimizer[0].options.terserOptions.compress.drop_console = trueconfig.optimization.minimizer[0].options.terserOptions.compress.drop_debugger = trueconfig.optimization.minimizer[0].options.terserOptions.compress.pure_funcs = ['console.log']}}
}
复制代码

配置完成后使用 vue inspect --mode=production > output.js 命令审查项目的 webpack 配置,optimization.minimizer的输出如下:

optimization: {minimizer: [{options: {test: /\.m?js(\?.*)?$/i,chunkFilter: () => true,warningsFilter: () => true,extractComments: false,sourceMap: false,cache: true,cacheKeys: defaultCacheKeys => defaultCacheKeys,parallel: true,include: undefined,exclude: undefined,minify: undefined,terserOptions: {output: {comments: /^\**!|@preserve|@license|@cc_on/i},compress: {arrows: false,collapse_vars: false,comparisons: false,computed_props: false,hoist_funs: false,hoist_props: false,hoist_vars: false,inline: false,loops: false,negate_iife: false,properties: false,reduce_funcs: false,reduce_vars: false,switches: false,toplevel: false,typeofs: false,booleans: true,if_return: true,sequences: true,unused: true,conditionals: true,dead_code: true,evaluate: true,warnings: false, drop_console: true, drop_debugger: true, pure_funcs: ['console.log']},mangle: {safari10: true}}}}],
}
复制代码

到此完成删除console.log的配置,接下来记录一下我踩到的坑~

坑1:在vue.config.js中直接使用terser-webpack-plugin后,通过vue inpect审查发现新增的compress参数并没有直接进入原有的terserOptions,而是minimizer数组新增了一个对象。这样导致vue-cli原有的terser-webpack-plugin配置失效。打包会以cache和parallel为false的配置下进行打包输出,打包速度变慢,因此后来采取直接修改terserOptions。

minimizer数组新增了一个对象:

options: {test: /\.m?js(\?.*)?$/i,chunkFilter: () => true,warningsFilter: () => true,extractComments: false,sourceMap: false,cache: false, cacheKeys: defaultCacheKeys => defaultCacheKeys,parallel: false,include: undefined,exclude: undefined,minify: undefined,terserOptions: {output: {comments: /^\**!|@preserve|@license|@cc_on/i},compress: {warnings: false,drop_console: true,drop_debugger: true,pure_funcs: ['console.log']}}
}
复制代码

坑2(未解决):在给.eslintrc.js的rules配置了no-console的情况下,修改代码后的首次打包eslint-loader总会在终端上报 error: Unexpected console statement (no-console),虽然打包过程中报错,但是最终的输出代码是没有console.log的;(使用babel-plugin-transform-remove-console删除console.log也会出现这种情况)

查看@vue/cli-plugin-eslint的源码发现eslint的cache属性为true,所以再次打包就不会对未修改的文件进行检测。

Eslint Node.js API对cache参数解释如下:

cache - Operate only on changed files (default: false). Corresponds to --cache.

cli-plugin-eslint使用eslint-loader的关键代码如下:

api.chainWebpack(webpackConfig => {webpackConfig.resolveLoader.modules.prepend(path.join(__dirname, 'node_modules'))webpackConfig.module.rule('eslint').pre().exclude.add(/node_modules/).add(require('path').dirname(require.resolve('@vue/cli-service'))).end().test(/\.(vue|(j|t)sx?)$/).use('eslint-loader').loader('eslint-loader').options({extensions,cache: true, cacheIdentifier,emitWarning: options.lintOnSave !== 'error',emitError: options.lintOnSave === 'error',eslintPath: resolveModule('eslint', cwd) || require.resolve('eslint'),formatter:loadModule('eslint/lib/formatters/codeframe', cwd, true) ||require('eslint/lib/formatters/codeframe')})})
复制代码

如果要终端不输出eslint的错误,可以在vue.config.js配置lintOnSave: process.env.NODE_ENV !== 'production'生产环境构建时禁用,但是这样与在eslintrc.js的rules中配置'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'off'的目的自相矛盾。

那么是否有办法让eslint-loader在terser-webpack-plugin或者babel-plugin-transform-remove-console之后进行检测呢?还是说配置了删除console.log就没必要配置'no-console'呢?希望有大神能回答我这个疑惑!

二、使用dllPlugin优化打包速度

网上已经有很多文章介绍dllPlugin的使用方法,这里就不介绍dllPlugin的详细配置说明了。本文只介绍一下针对vue-cli3项目使用webapck-chain方式的配置代码,所以就直接贴代码啦~

新增webpack.dll.config.js,代码如下:

const path = require('path')
const CleanWebpackPlugin = require('clean-webpack-plugin')
const webpack = require('webpack')module.exports = {mode: 'production',entry: {vendor: ['vue/dist/vue.runtime.esm.js', 'vuex', 'vue-router', 'element-ui'],util: ['lodash']},output: {filename: '[name].dll.js',path: path.resolve(__dirname, 'dll'),library: 'dll_[name]'},plugins: [new CleanWebpackPlugin(), // clean-wepback-plugin目前已经更新到2.0.0,不需要传参数pathnew webpack.DllPlugin({name: 'dll_[name]',path: path.join(__dirname, 'dll', '[name].manifest.json'),context: __dirname})]
}
复制代码

在vue.config.js添加DllReferencePlugin,最终代码如下:

const webpack = require('webpack')
const AddAssetHtmlPlugin = require('add-asset-html-webpack-plugin')
const path = require('path')const dllReference = (config) => {config.plugin('vendorDll').use(webpack.DllReferencePlugin, [{context: __dirname,manifest: require('./dll/vendor.manifest.json')}])config.plugin('utilDll').use(webpack.DllReferencePlugin, [{context: __dirname,manifest: require('./dll/util.manifest.json')}])config.plugin('addAssetHtml').use(AddAssetHtmlPlugin, [[{filepath: require.resolve(path.resolve(__dirname, 'dll/vendor.dll.js')),outputPath: 'dll',publicPath: '/dll'},{filepath: require.resolve(path.resolve(__dirname, 'dll/util.dll.js')),outputPath: 'dll',publicPath: '/dll'}]]).after('html')
}module.exports = {publicPath: '/',outputDir: 'dist',devServer: {port: 8080,https: false,hotOnly: true,disableHostCheck: true,open: true,},productionSourceMap: false, // 生产打包时不输出map文件,增加打包速度chainWebpack: config => {if (process.env.NODE_ENV === 'production') {dllReference(config)}},configureWebpack: config => {if (process.env.NODE_ENV === 'production') {config.optimization.minimizer[0].options.terserOptions.compress.warnings = falseconfig.optimization.minimizer[0].options.terserOptions.compress.drop_console = trueconfig.optimization.minimizer[0].options.terserOptions.compress.drop_debugger = trueconfig.optimization.minimizer[0].options.terserOptions.compress.pure_funcs = ['console.log']}}
}
复制代码

有3个地方需要说明一下:

1、webpack.dll.config.js文件中的entry.vendor使用'vue/dist/vue.runtime.esm.js'作为vue的入口,是根据vue inspect > output.js的文件中resolve.alias决定的;(vue.runtime.esm.js还是vue.esm.js取决于vue create构建时的选择)

resolve: {alias: {'@': '/Users/saki_bc/bccgithub/vue-webpack-demo/src',vue$: 'vue/dist/vue.runtime.esm.js'},
}
复制代码

2、在开发环境中不使用dllPlugin是因为chrome的vue devtool是不能检测压缩后的vue源码,使得没办法用vue devtool观察vue项目的组件和数据状态;

3、add-asset-html-webpack-plugin插件必须在html-webpack-plugin之后使用,因此这里要用webpack-chain来进行配置;至于为什么'html'代表html-webpack-plugin,是因为@vue/cli-servide/lib/config/app.js里是用plugin('html')来映射的,关键源码片段如下:

const HTMLPlugin = require('html-webpack-plugin')
webpackConfig.plugin('html').use(HTMLPlugin, [htmlOptions])
复制代码

4、这里不使用在index.html里添加script标签的方式引入dll文件,是因为当vue路由使用history模式,并且路由配置首页重定向到其他url的情况下,在首页刷新页面后dll文件会以重定向后的url的根目录引用,导致报错找不到dll文件。 如:dll的正确引用情况是http://www.xxx.com/vendor.dll.js,刷新重定向后变成 http://www.xxx.com/xxx/vendor.dll.js;即使在index.html使用绝对路径也是会出现这样的情况,目前还不知道是不是html-webpack-plugin的bug;

结语

这次优化实践仍然存在不少疑惑和且考虑的地方,webpack的更新发展也越来越快,vue-cli使用webpack-chain作为核心方式也增加了不少学习成本,接下来还需要阅读相关源码,发现项目中配置不合理的地方~

也希望各位大家能分享一下使用webpack4过程中踩到的坑~

相关文档

webpack-chain文档

add-asset-html-webpack-plugin文档

vue-cli配置源码

转载于:https://juejin.im/post/5c84b709e51d4578ca71dde4

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/449210.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

伤肾的九个恶习及解决办法(图)

近年来,很多人都在通过各种药物保护肾脏,其实,在生活中形成的各种不良饮食和生活习惯在不停地伤害你的肾,只是你未曾注意到而已。所以要保护好你的肾脏,必须从改变不良饮食和生活习惯开始。 不爱喝水 大部分男人对喝…

CC-BY-NC-SA (创作共用许可协议)

创作共用许可协议 (英语:Creative Commons license,简称CC许可) 是一种公共版权许可协议,其允许分发受版权保护的作品。一个创作共用许可,用于一个作者想给他人分享、使用、甚至创作派生作品的权利。创作共…

2020-3-31

题目一&#xff1a; 评论敏感词过滤代码&#xff0c;很多时候需要对一些评论或者文章中的敏感词进行过滤。 <!DOCTYPE html> <html> <head> <meta charset"utf-8"> </head> <script type"text/javascript"> window.o…

快速通读《现代软件工程——构建之法》

在快速通读《现代软件工程——构建之法》后&#xff0c;我有如下问题&#xff1a;Q1&#xff1a;第一章通过形象的例子告诉我们什么是软件工程&#xff0c;介绍了软件工程的各个阶段&#xff0c;对软件工程的概念及它的特性做了较为生动而详细的介绍&#xff0c;那么为什么需要…

Java 对象的序列化和反序列化

一.序列化和反序列化的概念 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 把对象转换为字节序列的过程称为对象的序列化。 把字节序列恢复为对象的过程称为对象的反序列化。 对象的序列…

不可重入锁和可重入锁

不可重入锁也叫自旋锁 指当一个方法调用了锁之后&#xff0c;如持有本锁的另一个方法也想执行&#xff0c;将会进入等待。那么想要使用这个方法必须先释放锁方可调用 public class Lock{private boolean isLocked false;public synchronized void lock() throws InterruptedEx…

家长必看 父母须知孩子社交圈九要点(组图)

孩子在慢慢的长大&#xff0c;总要接触外面的环境、接触到更多的人&#xff0c;也需要自己的社交圈。那么孩子的社交圈父母要知道9点。 1、妈妈是第一个“好朋友” 孩子社交的第一步从出生就开始了。虽然小小的他躺在那里还不能说话&#xff0c;但是通过哭、目光接触、笑等表…

2020-4-1

题目一 页面加载图片的时候&#xff0c;可能由于各种原因导致加载失败。 为了页面的人性化&#xff0c;在失败的时候通常会使用一张给定的图片替代。 <img src"logo.gif" onerror"javascript:this.srcdefault.gif" > //上面代码本来要加载logo.gif…

NGINX 配置超时时间

一、啥时候用到 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 用来设置请求资源和服务器返回的时间&#xff0c;保证一个请求占用固定时间&#xff0c;超出后报504超时&#xff01;这…

kettle变量(param命名参数)

1、定义&#xff1a; 编辑-设置-命名参数 在当前界面下定义参数名称和缺省值。 2、引用&#xff1a;原始数据 通过${var}引用变量 输出 注&#xff1a;1、字符串在命名参数引用是需要添加单引号的&#xff0c;但位置参数是不需要进行转译&#xff1b; 2、引用变量时需要勾选替换…

Excel操作

区间范围计算 方法一:用IF函数 方法二:构建一个辅助区域&#xff0c;用VLOOKUP函数 方法一:用IF函数 在F3中输入:IF(E3>90%,5%,IF(E3>80%,4%,IF(E3>70%,3%,IF(E3>60%,2%,1%)))) 向下拖动,搞定。 示例&#xff1a; IF(BB2<0.5,"50及以下",IF(AND(BB2&g…

养心灵,才能美容颜,拥有好日子(图)

“养心&#xff0c;就是在养颜”&#xff0c;说得多好啊。我们的脸是不会说谎的镜子&#xff0c;即使再巧妙的掩饰&#xff0c;也会在脸上显露出蛛丝马迹。 一个尖刻的人&#xff0c;嘴角的纹路必然多而杂;一个工于心计的人&#xff0c;脸色必定是阴沉暗淡的;一个无知的人&…

2020-4-2

题目一 利用事件冒泡原理实现了获取td单元格内容的功能。 <!DOCTYPE html> <html> <head> <meta charset" utf-8"> <style type"text/css"> #table{ width:300px; height:100px; border:1px solid #ccc; border-c…

AGC008D K-th K

题意简述&#xff1a;给你一个长度为\(N\)的整数序列\(x\)&#xff0c;请判断是否存在一个满足下列条件的整数序列\(a\)&#xff0c;如果存在&#xff0c;请构造一种方案。 1.\(a\)的长度为\(N^2\)并且满足数字\(1,2,3,\cdots,N\)都各出现恰好\(N\)次 2.对于\(1<i<N\)&am…

(一)prometheus与grafana介绍与安装

#&#xff08;1&#xff09;prometheus介绍 prometheus是一款 强大的监控系统和时序系统 采集数据&#xff1a; 在目标主机上安装exporter, exporter组件会在目标处收集监控数据, 并暴露一个http接口供prometheus查询, prometheus通过pull的方式来采集数据; 目前exporter已经采…

男人该知道的人生感悟(图)

一、家庭篇&#xff1a; 1、孝敬自己的父母&#xff0c;男人往往没有女人心细&#xff0c;所以你要经常提醒自己&#xff0c;常回家看看&#xff0c;不要等到“子欲养而亲不待”。 2、遇到事情&#xff0c;多听听父母的意见&#xff0c;他们是这个世界上最爱你的人。 3、好好…

2020-4-3

题目一 如何让IE8和IE8以下浏览器支持HTML5 <!–[if IE]> <script src"http://html5shiv.googlecode.com/svn/trunk/html5.js"></script> <![endif]–>上面这段代码仅会在IE浏览器下运行&#xff0c;还有一点需要注意&#xff0c;在页面中…

三维人脸前期调研

多张人脸照片进行3D人脸重建一种开源方法VisualSMeshlab目前的主流是VisualSFM&#xff08;找出各张照片中的特征点&#xff0c;进行两两匹配&#xff0c;根据匹配的结果&#xff0c;利用射影定理计算得到相机位置等场景信息&#xff0c;将场景信息与原始照片结合在一起得到照片…

git 报错:was cached in the local repository, resolution will not be reattempted until the upda

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 Could not resolve dependencies for project com.foreveross:gaei-syncpm:jar:0.0.1-SNAPSHOT: Failure to find com.oracle.jdbc:ojd…

6000个边缘Kubernetes节点驱动城市80万次智能停车,如何成为可能?

城市的街道因为汽车数量的增长越来越繁忙&#xff0c;对于驾车一族而言&#xff0c;在热门区域寻找停车场更是无比头痛的事情。然而与此同时&#xff0c;其实也许很多办公楼、住宅楼、酒店和公共车库中仍有许多付费停车的资源未被充分利用。 ParkBee就是这样一家为城市提供智能…