本文主要介绍如何在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

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

  1. vue-cli3.0 生产包去除console.log

    目前负责的公众号又迭代了一个版本,之前打生产包,配置总是和测试包搞混,所以使用了vue-cli3.0的环境变量来控制配置. 但是又发现了一个新问题,写代码的过程中写了很多console.log 来调试 ...

  2. 前端:一键清除项目中无用的console.log代码

    关注并将「趣谈前端」设为星标 每天定时分享技术干货/优秀开源/技术思维 前言 说起console.log调试,不用多说,那是非常的好用,开发中帮助我们解决了不少Bug.我们经常能在开发环境中看见这一坨 ...

  3. 如何移除项目中无用的 console.log 代码

    大家好,我是若川.早些天时,我看到一个后端公众号发<辞退了一个前端>,当时还想着现在后端公众号都开始吊打前端了嘛.其中有个理由就是线上还一堆console.log...我猜很多人都会移除项 ...

  4. 三行代码隐藏所有console.log

    我们基本上使用console.log()在JS项目中检查代码是否正常工作,或者debugger代码中的错误或问题.没有日志很费时,也很难找到问题. 但是这些日志只供开发人员使用,您不想向最终用户显示这 ...

  5. 一次性删除页面中所有console.log()

    在我们平日里做项目时,经常为了检查数据或者查看报错会使用console.log(),在控制台打印相应内容. 而通常写一些比较复杂的接口时会留下大量接口,我相信大多数朋友和我一样,写完以后都是继续写新的 ...

  6. vue main.js中引入js_手把手教你深入Vue3.0(Vue-cli4)项目打包性能优化实践

    记录了自己的博客在禁用缓存的情况下,从八九秒加载时间到最终985ms的优化实践,开启缓存的情况下能达到138ms的访问速度 本人的个人博客采用的是Vue-cli4.1.2 + typescript构建 ...

  7. 前端白屏问题_首页白屏优化实践

    前言 自从前端三大框架React.Vue.Angular面世以来,前端开发逐渐趋向规范化.统一化,大多数时候新建前端项目,首先想到使用的技术一定是三大框架之一,框架给前端开发带来了极大的便利和规范,但 ...

  8. 京东快递小程序分包优化实践

    前言- 随着项目规模增大,小程序分包优化是必须要面对的问题.分包不合理,不仅影响项目迭代和上线计划,还关乎用户体验,甚至因此导致 C 端用户流失.本文主要介绍京东快递小程序分包过程中踩过的坑,以及小程 ...

  9. vue 关闭log_vue或react项目生产环境去掉console.log的操作

    在开发环境写了很多console.log/info/debug,在生产环境需要去掉这些console. 如果手动删除未免也太累了,再说以后想再开发还得重新写console. 事实上webpack提供了 ...

最新文章

  1. json11库的使用
  2. nginx lua 安装spdy
  3. Storm/JStorm之TopologyBuilder源码阅读
  4. javascript-操作符
  5. 一般试卷的纸张大小是多少_pdf试卷怎么打印在A3纸上
  6. IOS 文本文字下面添加下划线
  7. java web 统计_Java web网站访问量的统计
  8. 狂奔的瑞幸咖啡讲了一个好故事 但还缺失一种 “感觉”
  9. SQL Server 查询分析工具
  10. 卖出跨式套利与买入蝶式价差
  11. C++,获取当前工作路径
  12. jq如何改变html页面,jq同一页面内容切换
  13. PeopleSoft开发:创建查询QUERY
  14. Loding缓存展示的写法-vue3
  15. adb shell 查看和修改电池信息
  16. 工业窑炉烟气SCR脱硝改造
  17. 【技术类】【ArcGIS对国产卫星的支持2:高分一号卫星】篇7、大规模影像管理
  18. AG9311功能应用和结构设计框图参考
  19. docker镜像上传
  20. 简单实用的记账软件,做到有账可查

热门文章

  1. nmon监控linux内存,使用Nmon监控Linux系统性能
  2. php 大型系统开法流程图,有一个php项目源码,如何搞清楚执行过程?画出其流程图...
  3. mysql授权 改表_mysql开启远程登陆(修改数据表和授权两种方法)
  4. android上传图片文件至c 服务器,Android 史上最优雅的实现文件上传、下载及进度的监听...
  5. dockerfile 安装mysql_dockerfile构建mysql镜像
  6. leetcode278. 第一个错误的版本
  7. 学点数学(5)--线性规划对偶形式的理解
  8. 使用CLion的时候,对于cmake的使用
  9. 算法入门篇八 贪心算法
  10. Android设计模式之——Builder模式