8000
We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
There was an error while loading. Please reload this page.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
本系列的主题是 Webpack,每期讲解一个技术要点。如果你还不了解各系列内容,文末点击查看全部文章,点我跳转到文末。
如果觉得本系列不错,欢迎 Star,你的支持是我创作分享的最大动力。
webpack性能优化主要指两个环境:
除了前面的开发环境和生产环境配置,还有以下性能优化处理:
开发环境性能优化包括:
生产环境性能优化包括:
为什么要使用HMR 热模块替换功能?
HMR 热模块替换
我们回看一下前面总结的开发环境配置:
/* 开发环境配置:能让代码运行 运行项目指令: webpack 打包运行项目 npx webpack-dev-server 启动webpack-dev-server */ const { resolve } = require('path'); const HtmlWebpackPlugin = require('html-webpack-plugin'); module.exports = { entry: './src/js/index.js', output: { filename: 'js/built.js', path: resolve(__dirname, 'build') }, module: { rules: [ // loader的配置 { // 处理less资源 test: /\.less$/, use: ['style-loader', 'css-loader', 'less-loader'] }, { // 处理css资源 test: /\.css$/, use: ['style-loader', 'css-loader'] }, { // 处理图片资源 test: /\.(jpg|png|gif)$/, loader: 'url-loader', options: { limit: 8 * 1024, name: '[hash:10].[ext]', // 关闭es6模块化 esModule: false, outputPath: 'imgs' } }, { // 处理html中img资源 test: /\.html$/, loader: 'html-loader' }, { // 处理其他资源 exclude: /\.(html|js|css|less|jpg|png|gif)/, loader: 'file-loader', options: { name: '[hash:10].[ext]', outputPath: 'media' } } ] }, plugins: [ // plugins的配置 new HtmlWebpackPlugin({ template: './src/index.html' }) ], mode: 'development', devServer: { contentBase: resolve(__dirname, 'build'), compress: true, port: 3000, open: true } };
下面我们看一下这种配置存在什么问题
运行指令:npx webpack-dev-server ,启动webpack-dev-server
npx webpack-dev-server
然后在index.js文件中打印一段话:console.log('index.js文件被加载了~');
index.js
console.log('index.js文件被加载了~');
只要index.js文件重新被加载,就会打印上面那段话
现在去修改样式文件
#box { width: 400px;// 200px修改为400px height: 200px; background-image: url('../imgs/angular.jpg'); background-repeat: no-repeat; background-size: 100% 100%; }
修改之后,很明显整体页面被刷新,内容被重新打印了一次
意思就是:当我们修改css文件时,明明js文件没有变化,但js文件也被重新加载了一次,所以打包的时候,看似只修改了css文件,实际上是把js文件也重新打包了一次,这是一个问题。
再写一个模块:
在index.js中引入上面那个print模块,并且在下面调用一下:
效果:
发现模块被加载,并且模块的print方法被调用执行了
现在我们修改一下print.js文件,'hello print'改为`'hello webpack'
'hello print'
console.log('print.js被加载了~'); function print() { const content = 'hello webpack'; console.log(content); } export default print;
保存查看效果,可以发现整个页面被重新刷新了,所有代码重新执行:
这个意思就代表:假设以后我们有100个js模块,100个样式模块,如果只修改其中某一个模块,这整200个模块就需要重新打包,这个速度可以想想是非常慢的,更不要说以后的模块会越来越多,那打包情况只会越来越慢。
所以我们想实现这样的功能:如果只有一个模块发生变化,那么只需要修改这一个模块代码就足够了,其他模块理应是不变的
做这个功能要使用webpack的HMR 热模块替换
HMR: hot module replacement 热模块替换 / 模块热替换
hot module replacement
作用:一个模块发生变化,只会重新打包这一个模块(而不是打包所有模块),极大提升构建速度
HMR功能的使用非常简单,只需要在devServer里配置hot:true即可:
hot:true
devServer: { contentBase: resolve(__dirname, 'build'), compress: true, port: 3000, open: true, // 开启HMR功能 // 当修改了webpack配置,新配置要想生效,必须重新webpack服务 hot: true }
修改配置后,运行指令:npx webpack-dev-server ,重新启动webpack-dev-server
开启HMR功能跟之前更新有什么区别?
首先打印结果这里已经显示HMR功能已经开启:
下面修改样式文件,保存,可以发现只更新一个样式文件,js文件并不会重新加载:
可以发现:样式文件可以使用HMR功能,之所以能使用是因为style-loader内部实现了~
这也是为什么我们在开发环境要使用style-loader,生产环境要用MiniCssExtractPlugin.loader提取成单独文件,因为开发环境借助style-loader能让性能更好,打包速度更快,但是上线的时候考虑性能优化,所以不能用
style-loader
MiniCssExtractPlugin.loader
前面样式文件可以使用HMR功能,js文件行不行呢?
修改print.js文件,保存,发现整个页面被重新刷新了一遍,这一点可以知道js文件默认不能使用HMR功能
print.js
html文件可以使用HMR功能吗?
在html文件中修改一段代码:
保存后发现当开启HMR功能后,html文件改动后并没有任何变化:
html文件: 默认不能使用HMR功能,同时会导致问题:html文件不能热更新了~
通过修改entey入口,改成一个数组,把html文件引入就可以解决上面的问题了:
entey
entry: ['./src/js/index.js', './src/index.html'],
修改配置后,打包运行项目
测试发现html文件也是没有HMR功能的,一旦html文件发生变化,整体页面就会重新刷新
那么html文件需要HMR功能吗?
html不像js文件,一个项目里会有很多个js模块,而运行的html只会有一个,一旦发生变化,就一定要变化,它只需要变化一个文件,既然一定要变化,那就没办法优化,所以html文件不用做HMR功能
前面讲到了js默认不能使用HMR功能,这并不代表js就不需要HMR功能,如何对js文件使用HMR功能?
用法:
if (module.hot) { // 一旦 module.hot 为true,说明开启了HMR功能。 --> 让HMR功能代码生效 module.hot.accept('./print.js', function() { // 方法会监听 print.js 文件的变化,一旦发生变化,其他模块不会重新打包构建。 // 会执行后面的回调函数 print(); }); }
修改print.js,查看效果
可以发现,print.js会重新更新,但index.js不会变,即index.js不会重新加载,样式和结构也不会重新加载,这就是js文件的HMR功能的使用
注意:HMR功能对js的处理,只能处理非入口js文件的其他文件。
为什么呢?
因为入口文件会将其他文件全部引入,一旦入口文件变化,其他文件重新引入,就会重新加载,这是没办法阻止的,所以入口文件是做不了HMR功能的,只能对入口文件引入的一些依赖或者其他文件做HMR功能。
比如修改入口文件下面的打印代码:
保存,可以发现所有东西都要重新打包构建:
查看全部文章
各系列文章汇总:https://github.com/yuanyuanbyte/Blog
我是圆圆,一名深耕于前端开发的攻城狮。
The text was updated successfully, but these errors were encountered:
yuanyuanbyte
No branches or pull requests
Uh oh!
There was an error while loading. Please reload this page.
本系列的主题是 Webpack,每期讲解一个技术要点。如果你还不了解各系列内容,文末点击查看全部文章,点我跳转到文末。
如果觉得本系列不错,欢迎 Star,你的支持是我创作分享的最大动力。
webpack性能优化
webpack性能优化主要指两个环境:
除了前面的开发环境和生产环境配置,还有以下性能优化处理:
开发环境性能优化包括:
生产环境性能优化包括:
HMR 热模块替换
为什么要使用
HMR 热模块替换
功能?我们回看一下前面总结的开发环境配置:
下面我们看一下这种配置存在什么问题
运行指令:
npx webpack-dev-server
,启动webpack-dev-server然后在
index.js
文件中打印一段话:console.log('index.js文件被加载了~');
只要index.js文件重新被加载,就会打印上面那段话
现在去修改样式文件
修改之后,很明显整体页面被刷新,内容被重新打印了一次
意思就是:当我们修改css文件时,明明js文件没有变化,但js文件也被重新加载了一次,所以打包的时候,看似只修改了css文件,实际上是把js文件也重新打包了一次,这是一个问题。
再写一个模块:
在index.js中引入上面那个print模块,并且在下面调用一下:
效果:
发现模块被加载,并且模块的print方法被调用执行了
现在我们修改一下print.js文件,
'hello print'
改为`'hello webpack'保存查看效果,可以发现整个页面被重新刷新了,所有代码重新执行:
这个意思就代表:假设以后我们有100个js模块,100个样式模块,如果只修改其中某一个模块,这整200个模块就需要重新打包,这个速度可以想想是非常慢的,更不要说以后的模块会越来越多,那打包情况只会越来越慢。
所以我们想实现这样的功能:如果只有一个模块发生变化,那么只需要修改这一个模块代码就足够了,其他模块理应是不变的
做这个功能要使用webpack的
HMR 热模块替换
HMR:
hot module replacement
热模块替换 / 模块热替换作用:一个模块发生变化,只会重新打包这一个模块(而不是打包所有模块),极大提升构建速度
HMR功能的使用非常简单,只需要在devServer里配置
hot:true
即可:修改配置后,运行指令:
npx webpack-dev-server
,重新启动webpack-dev-server开启HMR功能跟之前更新有什么区别?
首先打印结果这里已经显示HMR功能已经开启:
下面修改样式文件,保存,可以发现只更新一个样式文件,js文件并不会重新加载:
可以发现:样式文件可以使用HMR功能,之所以能使用是因为style-loader内部实现了~
这也是为什么我们在开发环境要使用
style-loader
,生产环境要用MiniCssExtractPlugin.loader
提取成单独文件,因为开发环境借助style-loader
能让性能更好,打包速度更快,但是上线的时候考虑性能优化,所以不能用前面样式文件可以使用HMR功能,js文件行不行呢?
修改
print.js
文件,保存,发现整个页面被重新刷新了一遍,这一点可以知道js文件默认不能使用HMR功能html文件可以使用HMR功能吗?
在html文件中修改一段代码:
保存后发现当开启HMR功能后,html文件改动后并没有任何变化:
html文件: 默认不能使用HMR功能,同时会导致问题:html文件不能热更新了~
通过修改
entey
入口,改成一个数组,把html文件引入就可以解决上面的问题了:修改配置后,打包运行项目
测试发现html文件也是没有HMR功能的,一旦html文件发生变化,整体页面就会重新刷新
那么html文件需要HMR功能吗?
html不像js文件,一个项目里会有很多个js模块,而运行的html只会有一个,一旦发生变化,就一定要变化,它只需要变化一个文件,既然一定要变化,那就没办法优化,所以html文件不用做HMR功能
前面讲到了js默认不能使用HMR功能,这并不代表js就不需要HMR功能,如何对js文件使用HMR功能?
用法:
修改
print.js
,查看效果可以发现,
print.js
会重新更新,但index.js
不会变,即index.js
不会重新加载,样式和结构也不会重新加载,这就是js文件的HMR功能的使用注意:HMR功能对js的处理,只能处理非入口js文件的其他文件。
为什么呢?
因为入口文件会将其他文件全部引入,一旦入口文件变化,其他文件重新引入,就会重新加载,这是没办法阻止的,所以入口文件是做不了HMR功能的,只能对入口文件引入的一些依赖或者其他文件做HMR功能。
比如修改入口文件下面的打印代码:
保存,可以发现所有东西都要重新打包构建:
参考
查看全部文章
博文系列目录
交流
各系列文章汇总:https://github.com/yuanyuanbyte/Blog
我是圆圆,一名深耕于前端开发的攻城狮。
The text was updated successfully, but these errors were encountered: