webpack打包优化分为两部分,一部分是大小优化,另一部分是速度优化。

大小优化

1.CommonsChunk

前端构建项目中,为了提高打包效率,往往将第三库与业务逻辑代码分开打包,因为第三方库往往不需要经常打包更新。webpack建议使用CommonsChunk 来单独打包第三方库:

module.exports = {entry: {vendor: ['react','react-dom'],app: "./main",},output: {path: './build',filename: '[name].js',library: '[name]_library'},plugins: [new CommonsChunkPlugin({name: "vendor",}),]
};

CommonsChunk虽然可以减少包的大小,但存在问题是:即使代码不更新,每次重新打包,vendor都会重新生成,不符合我们分离第三方包的初衷。

2.Externals

相比于前者,webpack 提供Externals的方法,可以通过外部引用的方法,引入第三方库: index.html

<script src="https://code.jquery.com/jquery-3.1.0.js"></script>

webpack.config.js

module.exports = {externals: {jquery: 'jQuery'}
};

业务逻辑,如index.js

import $ from 'jquery';
$('.my-element').animate(...);

webpack遇到此问题时,会重新打包react代码。 参考:https://gold.xitu.io/entry/57996222128fe1005411c649

3.DLL & DllReference

相比于前者,通过前置这些依赖包的构建,来提高真正的build和rebuild构建效率。也就是说只要第三方库没有变化,之后的每次build都只需要去打包自己的业务代码,解决Externals多次引用问题。 webpack通过webpack.DllPlugin与webpack.DllReferencePlugin两个内嵌插件实现此功能。
1、新建webpack.dll.config.js

const webpack = require('webpack');module.exports = {entry: {bundle: ['react','react-dom',//其他库],},output: {path: './build',filename: '[name].js',library: '[name]_library'},plugins: [new webpack.DllPlugin({path: './build/bundle.manifest.json',name: '[name]_library',})]
};

webpack.DllPlugin选项:

  • path:manifest.json文件的输出路径,这个文件会用于后续的业务代码打包;
  • name:dll暴露的对象名,要跟output.library保持一致;
  • context:解析包路径的上下文,这个要跟接下来配置的 webpack.config.js 一致。

运行:

npm run webpack-dll

生成两个文件,一个是打包好的bundlejs,另外一个是bundle.mainifest.json,大致内容如下:

{"name": "bundle_library","content": {"./node_modules/react/react.js": 1,"./node_modules/react/lib/React.js": 2,"./node_modules/process/browser.js": 3,"./node_modules/object-assign/index.js": 4,"./node_modules/react/lib/ReactChildren.js": 5,"./node_modules/react/lib/PooledClass.js": 6,"./node_modules/react/lib/reactProdInvariant.js": 7,//其他引用
}

2、配置webpack.config.js

const webpack = require('webpack');
var path = require('path');
module.exports = {entry: {main: './main.js',},output: {path: path.join(__dirname, "build"),publicPath: './',filename: '[name].js'},module: {loaders:[{ test: /\.(png|jpg)$/, loader: 'url-loader?limit=8192'},{test: /\.jsx?$/,loaders: ['babel-loader?presets[]=es2015&presets[]=react'],include: path.join(__dirname, '.')}]},plugins: [new webpack.DllReferencePlugin({context: '.',manifest: require("./build/bundle.manifest.json"),}),]
};

webpack.DllReferencePlugin的选项中:

  • context:需要跟之前保持一致,这个用来指导webpack匹配manifest.json中库的路径;
  • manifest:用来引入刚才输出的manifest.json文件。

速度优化

1.优化loader配置

1.1 缩小文件匹配范围(include/exclude)

通过排除node_modules下的文件 从而缩小了loader加载搜索范围 高概率命中文件


module: {rules: [{test: /\.js$/,use: 'babel-loader',exclude: /node_modules/, // 排除不处理的目录include: path.resolve(dirname, 'src') // 精确指定要处理的目录}]}

1.2 缓存loader的执行结果(cacheDirectory)

cacheDirectory是loader的一个特定的选项,默认值是false。指定的目录(use: ‘babel-loader?cacheDirectory=cacheLoader’)将用来缓存loader的执行结果,减少webpack构建时Babel重新编译过程。如果设置一个空值(use: ‘babel-loader?cacheDirectory’) 或true(use: ‘babel-loader?cacheDirectory=true’) 将使用默认的缓存目录(node_modules/.cache/babel-loader),如果在任何根目录下都没有找到 node_modules 目录,将会降级回退到操作系统默认的临时文件目录。

module: {rules: [{test: /\.js$/,use: 'babel-loader?cacheDirectory', // 缓存loader执行结果 发现打包速度已经明显提升了exclude: /node_modules/,include: path.resolve(dirname, 'src')}]}

 2.resolve优化配置

2.1 优化模块查找路径 resolve.modules

Webpack的resolve.modules配置模块库(即 node_modules)所在的位置,在 js 里出现 import ‘vue’ 这样不是相对、也不是绝对路径的写法时,会去 node_modules 目录下找。但是默认的配置,会采用向上递归搜索的方式去寻找,但通常项目目录里只有一个 node_modules,且是在项目根目录,为了减少搜索范围,可以直接写明 node_modules 的全路径;同样,对于别名(alias)的配置,亦当如此:

const path = require('path');function resolve(dir) { // 转换为绝对路径return path.join(dirname, dir);}resolve: {modules: [ // 优化模块查找路径path.resolve('src'),path.resolve('node_modules') // 指定node_modules所在位置 当你import 第三方模块时 直接从这个路径下搜索寻找]}

配置好src目录所在位置后,由于util目录是在src里面 所以可以用下面方式引入util中的工具函数


// main.jsimport dep1 from 'util/dep1';import add from 'util/add';

2.2 resolve.alias 配置路径别名

创建 import 或 require 的路径别名,来确保模块引入变得更简单。配置项通过别名来把原导入路径映射成一个新的导入路径 此优化方法会影响使用Tree-Shaking去除无效代码。
例如,一些位于 src/ 文件夹下的常用模块:


alias: {Utilities: path.resolve(dirname, 'src/utilities/'),Templates: path.resolve(dirname, 'src/templates/')}

现在,替换「在导入时使用相对路径」这种方式,就像这样:

import Utility from '../../utilities/utility';

你可以这样使用别名:

import Utility from 'Utilities/utility';
resolve: {alias: { // 别名配置 通过别名配置 可以让我们引用变的简单'vue$': 'vue/dist/vue.common.js', // $表示精确匹配src: resolve('src') // 当你在任何需要导入src下面的文件时可以 import moduleA from 'src/moduleA' src会被替换为resolve('src') 返回的绝对路径 而不需要相对路径形式导入}}

也可以在给定对象的键后的末尾添加 $,以表示精准匹配:

alias: {util$: resolve('src/util/add.js')}

这将产生以下结果:

import Test1 from 'util'; // 精确匹配,所以 src/util/add.js 被解析和导入import Test2 from 'util/dep1.js'; // 精确匹配,触发普通解析 util/dep1.js

2.3resolve.extensions

当引入模块时不带文件后缀 webpack会根据此配置自动解析确定的文件后缀

后缀列表尽可能小

频率最高的往前放

导出语句尽可能带上后缀

resolve: {extensions: ['.js', '.vue']}

3.module.noParse

用了noParse的模块将不会被loaders解析,所以当我们使用的库如果太大,并且其中不包含import require、define的调用,我们就可以使用这项配置来提升性能, 让 Webpack 忽略对部分没采用模块化的文件的递归解析处理。

// 忽略对jquery lodash的进行递归解析module: {// noParse: /jquery|lodash/// 从 webpack 3.0.0 开始noParse: function(content) {return /jquery|lodash/.test(content)}}

4.HappyPack

HappyPack是让webpack对loader的执行过程,从单一进程形式扩展为多进程模式,也就是将任务分解给多个子进程去并发的执行,子进程处理完后再把结果发送给主进程。从而加速代码构建 与 DLL动态链接库结合来使用更佳。

npm i happypack@next -D

webpack.config.js

const HappyPack = require('happypack');const os = require('os'); // node 提供的系统操作模块// 根据我的系统的内核数量 指定线程池个数 也可以其他数量const happyThreadPool = HappyPack.ThreadPool({size: os.cpus().lenght})module: {rules: [{test: /\.js$/,use: 'happypack/loader?id=babel',exclude: /node_modules/,include: path.resolve(dirname, 'src')}]},plugins: [new HappyPack({ // 基础参数设置id: 'babel', // 上面loader?后面指定的idloaders: ['babel-loader?cacheDirectory'], // 实际匹配处理的loaderthreadPool: happyThreadPool,// cache: true // 已被弃用verbose: true});]

happypack提供的loader,是对文件实际匹配的处理loader。这里happypack提供的loader与plugin的衔接匹配,则是通过id=happypack来完成。

5.ParallelUglifyPlugin

这个插件可以帮助有很多入口点的项目加快构建速度。把对JS文件的串行压缩变为开启多个子进程并行进行uglify。

cnpm i webpack-parallel-uglify-plugin -D
// webpck.config.jsconst ParallelUglifyPlugin = require('webpack-parallel-uglify-plugin');plugins: [new ParallelUglifyPlugin({workerCount: 4,uglifyJS: {output: {beautify: false, // 不需要格式化comments: false // 保留注释},compress: { // 压缩warnings: false, // 删除无用代码时不输出警告drop_console: true, // 删除console语句collapse_vars: true, // 内嵌定义了但是只有用到一次的变量reduce_vars: true // 提取出出现多次但是没有定义成变量去引用的静态值}}});]

执行压缩

webpack --mode production

6.Tree Shaking

剔除JavaScript中用不上的代码。它依赖静态的ES6模块化语法,例如通过impot和export导入导出

参考链接:
webpack dllPlugin 使用
https://gold.xitu.io/entry/57996222128fe1005411c649

Webpack打包和优化相关推荐

  1. webpack 打包编译优化之路

    一.摘要 从最初的html css js 混合编程,到分离编程.再到用上各种框架 react vue angular , 伴随着框架和模块化的概念铺开,打包编译工具渐渐浮出水面.从2013年开始使用打 ...

  2. 记一次 webpack 打包体积优化

    手头做的项目开发得差不多了,而打包配置是一开始粗略配置的,不大的项目打包出来得6MB+,所以现在必须进行优化. 打包结果分析 执行命令 webpack --profile --json > st ...

  3. webpack打包优化(webpack打包优化 文件大小)

    webpack 打包怎么优化的 解决webpack打包的文件体积过大的问题: 确实,每次打包从入口开始,会parse所有的依赖,多的时候竟然打包一次要2秒多,简直不能忍.然而,有几个解决方案,最有效的 ...

  4. webstrom中打包的详细_webpack打包体积优化

    webpack webpack打包体积优化 webpack官方定义 webpack 是一个模块打包器.webpack 的主要目标是将 JavaScript 文件打包在一起,打包后的文件用于在浏览器中使 ...

  5. webpack打包优化_前端性能优化:webpack性能调优与Gzip原理

    链接:https://juejin.im/book/5b936540f265da0a9624b04b 从输入 URL 到显示页面这个过程中,涉及到网络层面的,有三个主要过程: DNS 解析 TCP 连 ...

  6. webpack打包vue反编译_2020年你必须知道的webpack打包优化方法

    本文字数:3534字 预计阅读时间:10分钟 随着我们的项目项目越做越大,引入的第三方库会越来越多,打包的依赖也越来越多,每次 build 的时间越来越长,打包出来的文件会越来越大.最糟糕的是单页面应 ...

  7. 把html压缩成dll,一篇文章带你浅入webpack的DLL优化打包

    一.前言 我们在使用第三方包的时候,一般内部的代码都不会变,但是当webpack打包的时候,还是回去处理第三方包.我们是否可以利用一些方法来改进呢?我们可以先对第三方包处理,然后再打包. 二.实战 1 ...

  8. webpack打包优化之外部扩展externals的实际应用

    目录 前言 externals定义 用法 string array object function regex 实际案例 打包时间 打包之后包的大小 浏览器加载 需要注意 参考 前言 使用vue-cl ...

  9. 看看webpack打包优化

    webpack 打包策略,主要有下列几种方法. 1.CDN2.DllPlugin3.splitChunks4.happypack 下面详细介绍使用的流程. CDN 通常使用的第三方模块很大时,但是又想 ...

最新文章

  1. 《Linux内核分析》实践4
  2. RK1109 RK1126等芯片来袭,2020年瑞芯微旗下SoC一览
  3. unicode转中文的工具
  4. 简洁的MobX与MVP思想—大型项目实践
  5. 深度学习试题_高中生物:今年高考试题3点显著变化及5个备考建议!不看准吃亏...
  6. Mac OS使用技巧十八:Safari碉堡功能之一制作Widget
  7. C++从0到1的入门级教学(六)——函数
  8. ubuntu18.04 Qt Creator 安装+ROS Qt Creator Plug-in 插件安装笔记
  9. JAVA awt eventqueue_线程“AWT-EventQueue-1”中的异常java.lang.NullPointerException
  10. linux文件夹做链接,linux为什么不能给目录做硬链接
  11. 关于FlexPaper 2.1.2版本 二次开发 Logo 、打印、搜索、缩略图、添加按钮、js交互、右键菜单等相关问题...
  12. Steve Thair谈DevOps on Windows的演变与面临的挑战
  13. html中遍历表单,萌新提问!!!如何用for循环循环表单?
  14. Self Host WebApi服务传输层SSL加密(服务器端+客户端调用)
  15. 通过sudo提权方式控制公司人员权限
  16. 伽罗华有限域_信息论与编码:有限域
  17. Playrix Codescapes Cup (Codeforces Round #413, rated, Div. 1 + Div. 2) F. Beautiful fountains rows
  18. CSP-M2 B - HRZ 学英语
  19. 计算机检测不到双显示器,win10系统双屏幕检测不到第二屏幕怎么办 解决双屏幕不显示的方法步骤...
  20. 2021-04-19

热门文章

  1. 如何清除计算机的u盘使用记录,win7如何删除u盘使用记录?win7清除u盘使用痕迹方法...
  2. python创建一个空集合_Python中如何创建集合
  3. 电脑硬盘磁盘不小心被格式化了?如何一键恢复操作教程
  4. 京东B2B业务架构演变读后感
  5. myeclipse9解决shortcut name changed
  6. RPO和RTO的区别
  7. 性能测试sysbench之cpu性能测试
  8. 更改Ubuntu 的登录背景图片
  9. 骨刻文字数字化识别1
  10. excel如何去重统计户数_去重条件计数(excel去重统计个数)