webpack简介
webpack 是一个现代 JavaScript 应用程序的静态模块打包器(module bundler)。当 webpack 处理应用程序时,它会递归地构建一个依赖关系图(dependency graph),其中包含应用程序需要的每个模块,然后将所有这些模块打包成一个或多个 bundle。
核心概念:入口,出口,loader,插件
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin'); // 通过 npm 安装
const webpack = require('webpack'); // 用于访问内置插件
module.exports = {
entry: './path/to/my/entry/file.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'my-first-webpack.bundle.js'
},
module: {
rules: [
{ test: /\.txt$/, use: 'raw-loader' }
]
},
plugins: [
new HtmlWebpackPlugin({template: './src/index.html'})
]
};
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
babel plugin preset区别
Babel是代码转换器,比如将ES6转成ES5,或者将JSX转成JS等。借助Babel,开发者可以提前用上新的JS特性,这对生产力的提升大有帮助。
实现Babel代码转换功能的核心,就是Babel插件(plugin)。
Babel插件一般尽可能拆成小的力度,开发者可以按需引进。比如对ES6转ES5的功能,Babel官方拆成了20+个插件。
这样的好处显而易见,既提高了性能,也提高了扩展性。比如开发者想要体验ES6的箭头函数特性,那他只需要引入transform-es2015-arrow-functions插件就可以,而不是加载ES6全家桶。
但很多时候,逐个插件引入的效率比较低下。比如在项目开发中,开发者想要将所有ES6的代码转成ES5,插件逐个引入的方式令人抓狂,不单费力,而且容易出错。
这个时候,可以采用Babel Preset。
可以简单的把Babel Preset视为Babel Plugin的集合。比如babel-preset-es2015就包含了所有跟ES6转换有关的插件。
webpack常用插件
loader用于打包文件,plugins 用于解决一些其他任务,比如去注释等等。
- HTML文件生成插件:html-webpack-plugin
产生背景:多入口时,当你的 index.html 引入多个js,如果这些生成的js名称构成有 [hash] ,那么每次打包后的文件名都是变化的。
作用:HtmlWebpackPlugin 在此可以用于自动重新生成一个index.html或依据模板生成,帮你把所有生产的js文件引入到html中,最终生成到output目录。
安装:
npm install --save-dev html-webpack-plugin
配置:
const HtmlWebpackPlugin = require('html-webpack-plugin');
plugins: [
new HtmlWebpackPlugin()
]
2
3
4
- 图片压缩插件:imagemin-webpack-plugin
产生背景:图片过大,加载速度慢,浪费存储空间。
作用:批量压缩图片。
安装:
npm install --save-dev imagemin-webpack-plugin
配置:
//引入插件
var ImageminPlugin = require('imagemin-webpack-plugin').default;
//配置
plugins: [
new ImageminPlugin({
disable: process.env.NODE_ENV !== 'production', // 开发时不启用
pngquant: {//图片质量
quality: '95-100'
}
})
]
2
3
4
5
6
7
8
9
10
11
12
- css提取插件:clean-webpack-plugin (生产模式)
产生背景:在进行打包时,css代码会打包到JS中,不利于文件缓存。
作用:依据每个entry生成单个css文件(将css从js中提取出来)。
安装:
npm install --save-dev mini-css-extract-plugin
配置:
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
plugins: [
new MiniCssExtractPlugin(),
]
2
3
4
注意:不要在开发模式使用,因为不支持热加载
如果单入口,不需要这个
- css 去除无用的样式
产生背景:编写的css可能出现冗余情况。
作用:去除冗余的css代码。
安装:
npm install --save-dev purifycss-webpack
配置:
const purifycssWebpack = require('purifycss-webpack');
const glob = require('glob');
// Make sure this is after ExtractTextPlugin!
new purifycssWebpack({
paths: glob.sync(path.resolve('./src/*.html'))
}),
2
3
4
5
6
7
注意:html文件生成 > css提取 > css摇树 参考文档
content-hash和hash区别
hash:跟整个项目的构建相关,构建生成的文件hash值都是一样的,只要项目里有文件更改,整个项目构建的hash值都会更改。 chunkhash:根据不同的入口文件(Entry)进行依赖文件解析、构建对应的chunk,生成对应的hash值。 contenthash:由文件内容产生的hash值,内容不同产生的contenthash值也不一样。
显然,我们是不会使用第一种的。改了一个文件,打包之后,其他文件的hash都变了,缓存自然都失效了。这不是我们想要的。 那chunkhash和contenthash的主要应用场景是什么呢?在实际在项目中,我们一般会把项目中的css都抽离出对应的css文件来加以引用。如果我们使用chunkhash,当我们改了css代码之后,会发现css文件hash值改变的同时,js文件的hash值也会改变。这时候,contenthash就派上用场了。
HMR(Hot Module Replacement)热更新原理
HMR是指当你对代码修改并保存后,webpack将会对代码进行重新打包,并将改动的模块发送到浏览器端,浏览器用新的模块替换掉旧的模块,去实现局部更新页面而非整体刷新页面。
Server端使用webpack-dev-server去启动本地服务,内部实现主要使用了webpack、express、websocket。
使用express启动本地服务,当浏览器访问资源时对此做响应。
服务端和客户端使用websocket实现长连接
webpack监听源文件的变化,即当开发者保存文件时触发webpack的重新编译。
- 每次编译都会生成hash值、已改动模块的json文件、已改动模块代码的js文件
- 编译完成后通过socket向客户端推送当前编译的hash戳
客户端的websocket监听到有文件改动推送过来的hash戳,会和上一次对比
- 一致则走缓存
- 不一致则通过ajax和jsonp向服务端获取最新资源
使用内存文件系统去替换有修改的内容实现局部刷新
← 事件循环 canvas svg→