Webpack4优化之路

简介

Webpack4 那点儿东西 基于webpack4总结了一些webpack的常见配置,可是webpack 各类强大的配置有时候让你不堪重负,会打包不少的文件,遍历解析不少文件。。。。。总之,这些操做会让webpack打包过程变得很慢,因此开发过程当中咱们不得不去优化一些配置,让webpack更好的服务于咱们的开发。vue

动态连接库DLL

即把基础模块的代码打包进入动态连接库里,好比经常使用的react,vue等,当须要导入的模块在动态链接库里的时候,模块不能再次被打包,而是去动态链接库里获取node

  1. 建立一个webpack.dll.config.js文件打包经常使用类库到dll中
module.exports = {
    entry: {
        react: ['vue'] //vue模块打包到一个动态链接库
    },
    output: {
        path: path.resolve(__dirname, 'dist'),
        filename: '[name].dll.js', //输出动态链接库的文件名称
        library: '_dll_[name]' //全局变量名称
    },
    plugins: [
        new webpack.DllPlugin({
            name: '_dll_[name]', //和output.library中一致,也就是输出的manifest.json中的 name值
            path: path.join(__dirname, 'dist', '[name].manifest.json')
        })
    ]
}
webpack --config webpack.dll.config.js --mode production
复制代码
  1. 在住配置文件 webpack.config.js中加入如下代码
plugins: [
 new webpack.DllReferencePlugin({
       manifest: require(path.join(__dirname, 'dist', 'vue.manifest.json')),
   })
]
webpack --config webpack.config.js --mode development
复制代码

这样会从dll中获取vue,并且不用再次打包vue了。react

Webpack热替换之HMR

Hot Module Replacement(如下简称 HMR)是 webpack 中超级有用的特性之一 ,当你对代码进行修改并保存后,webpack 将对代码从新打包,并将新的模块发送到浏览器端,浏览器经过新的模块替换老的模块,这样在不刷新浏览器的前提下就可以对应用进行更新。从而减小不少时间。の。。。。好比,页面中有一个modal框,须要点击button触发modal显示,在开发过程当中,若是修改了modal 的样式,触发浏览器刷新,你还须要再次点击button才能看到修改后的modal样式,可是热替换是不须要刷新浏览器的,能够直接观察到修改后的变化。 上文中已经介绍了watch的用法,可是watch是针对打包时文件发生变化进行从新打包,而HMR是针对webpack-dev-server的。webpack

  1. devserver配置以下
devServer: {//配置此静态文件服务器,能够用来预览打包后项目
    inline:true,//打包后加入一个websocket客户端
    hot:true,//热加载
    contentBase: path.resolve(__dirname, 'dist'),//开发服务运行时的文件根目录
    host: 'localhost',//主机地址
    port: 9090,//端口号
    compress: true//开发服务器是否启动gzip等压缩
}
复制代码
  1. plugins配置项加入如下两行
new webpack.HotModuleReplacementPlugin(),
 new webpack.NamedModulesPlugin()//用户名替代id
复制代码

3.业务代码中的修改git

if(module.hot) {
    module.hot.accept('./hello.js', function() {
        div.innerHTML = hello()
    })
}
复制代码
  1. 原理及流程解析大体流程: webpack-dev-server能够和浏览器之间创建一个web socket进行通讯,一旦新文件被打包出来,webpack-dev-server就告诉浏览器这个消息,这时浏览器就能够自动刷新页面或者进行热替换操做。当一个模块b发生改变,而模块内又没有HMR代码(相似于上述3中的代码)来处理这一消息时,那这一消息就会被传递到依赖模块b的其余模块上;若是消息在新模块上没有被捕获的话就会再次进行传递;若是全部的消息都被捕获了的话,那咱们的应用就应该已经按照代码进行了更新;反之若是有消息冒泡到了入口(entry)文件尚未被捕获的话,那就说明咱们的代码中没有处理这类变动方法,那webpack就会刷新浏览器页面,即从HMR回退到LiveReload。

Tree Shaking

tree shaking 是一个术语,一般用于描述移除 JavaScript 上下文中的未引用代码。这个术语和概念其实是兴起于 ES2015 模块打包工具 rollup。你能够将应用程序想象成一棵树。绿色表示实际用到的源码和 library,是树上活的树叶。灰色表示无用的代码,是秋天树上枯萎的树叶。为了除去死去的树叶,你必须摇动这棵树,使它们落下。可是webpakc的Tree Shaking依赖静态的ES6模块化语法即经过import和export导入导出的代码,并且须要引入一个可以删除未引用代码(dead code)的压缩工具(minifier)(例如 UglifyJSPlugin)或者在运行命令的时候用webpack --display-used-exports --optimize-minimize --mode productiongithub

好比如下代码web

export function getName() {
    return 'hello world';
}
export function getAge() {
    return 9999;
}
复制代码

若是你只引用了其中一个,那么经过Tree Shaking会剔除另外一个未用到的,打包的时候直接忽略。json

{
    test: /\.js/,
    use: {
        loader: 'babel-loader',
        query: {
            presets: ["env", {
+                                   modules: false //关闭 Babel 的模块转换功能,保留本来的 ES6 模块化语法
+                               }]
        }
    }
}
const UglifyJSPlugin = require('uglifyjs-webpack-plugin');
plugins: [
    new UglifyJSPlugin()
 ]
webpack --display-used-exports --optimize-minimize
复制代码

提取公共代码

这个变化仍是很大的,以前的webpack版本用的都是commonchunkplugin,可是webpack4开始使用common-chunk-and-vendor-chunk 配置以下:浏览器

optimization: {
	splitChunks: {
		cacheGroups: {
			commons: {
				chunks: "initial",
				minChunks: 2,
				maxInitialRequests: 5, // The default limit is too small to showcase the effect
				minSize: 0 // This is example is too small to create commons chunks
			},
			vendor: {
				test: /node_modules/,
				chunks: "initial",
				name: "vendor",
				priority: 10,
				enforce: true
			}
		}
	}
}
复制代码

Scope Hoisting

做用域提高,这是在webpack3中所提出来的。它会使代码体积更小,由于函数申明语句会产生大量代码.bash

const ModuleConcatenationPlugin = require('webpack/lib/optimize/ModuleConcatenationPlugin');
plugins: [
// 开启 Scope Hoisting
new ModuleConcatenationPlugin(),
],
复制代码

CDN

对于静态资源的处理,放入CDN是一个很好的选择,webpack中配置CDN的方式以下:

output: {
    path: path.resolve(__dirname, 'dist'),
    filename: '[name]_[hash:8].js',
    publicPath: 'http://static.xxxx.com/'
},
复制代码

多进程之HappyPack

HappyPack就能让Webpack把任务分解给多个子进程去并发的执行,子进程处理完后再把结果发送给主进程,其中子进程的个数为cpu的个数减去1,须要在loader处修改以下

use: 'happypack/loader?id=babel',
复制代码

而且在plugin中添加如下代码:

new HappyPack({
    id: 'babel',
    //如何处理.js文件,和rules里的配置相同
    loaders: [{
        loader: 'babel-loader',
        query: {
            presets: [
                "env", "stage-0"
            ]
        }
    }]
}),
复制代码

小结

以上为webpack配置中的一些常见优化方案,可是根据项目的不一样,须要选择的方案也不太同样,多尝试,根据特定的环境选择特定的优化方案,我以为是一件比较不错的事情。

相关文章
相关标签/搜索