webpack 的常用插件
html-webpack-plugin: 将一个页面模版打包到dist目录下,默认都是自动引入js 和 css
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
plugins: [
new HtmlWebpackPlugin({
template: './index.html', // 以咱们本地的index.html文件为基础模板
filename: "index.html", // 输出到dist目录下的文件名称 }),
]
}
clean-webpack-plugin: 每次打包dist目录删除
const {
CleanWebpackPlugin } = require('clean-webpack-plugin');
module.exports = {
plugins: [
new CleanWebpackPlugin()
]
}
extract-text-webpack-plugin :将css样式从js文件中提取出来最终合成一个css文件,该插件只支持webpack4之前的版本
const extractTextPlugin = require('extract-text-webpack-plugin');
module.exports = {
module: {
rules: [
{
test: /\.css$/,
use: extractTextPlugin.extract({
fallback: "style-loader", //当提取不成功时,就执行style-loader
use: "css-loader" //提取时使用css-loader进行转换
})
}
]
},
plugins: [
new extractTextPlugin({
filename: "[name].css", //filename是最后合并完的.css文件名称
allChunks: true //,当allChunks为false时,只会提取初始化时的css文件,为true时会提取异步的css文件
})
]
}
mini-css-extract-plugin :该插件与上面的exract-text-webpack-plugin
的一样,都是将css样式提取出来, 唯一就是用法不同,本插件的webpack4版本之后推荐使用
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = {
module: {
rules: [
{
test: /\.css$/,
use: [
MiniCssExtractPlugin.loader,
"css-loader"
]
}
]
},
plugins: [
new MiniCssExtractPlugin({
filename: "css/[name].css",
chunkFilename: "css/[name].css"
})
]
}
上面配置中,可以看到用法与exract-text-webpack-plugin
不同,来看一下它们的区别。
- loader配置没有fallback
- 在plugin中设置filename同步加载资源名称,还要指定异步加载css资源chunkFilename
- 该插件支持配置publicPath用来设置异步加载css的路径
- exract-text-webpack-plugin只会提取一个css文件,mini-css-extract-plugin会根据异步文件提取出来。
webpack.optimize.CommonsChunkPlugin:用于将页面里的公共代码提取出来,从而进行优化加载速度,该CommonsChunkPlugin只支持webpack4之前版本。
module.exports = {
entry: {
main: "./main.js", //main.js及它里面的依赖文件把Vue.js提取出来进行优化
vendor: ["Vue"] //避免每次打包或者每次访问其它页面都加载一个该js文件, 我们先是把Vue基础环境提取出来
},
plugins: [
new Webpack.optimize.CommonsChunkPlugin({
name: "vendor",
filename: "[name].js"
}),
new Webpack.optimize.CommonsChunkPlugin({
name: "common",
chunks: ["vendor"],
filename: "[name].js"
})
]
}
hot-module-replacem-plugin :开启热更新模块
const Webpack = require("webpack")
module.exports = {
plugins: [
new Webpack.HotModuleReplacementPlugin()
]
}
uglifyjs-webpack-plugin :用于压缩js文件,针对webpack4之前版本
const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
module.exports = {
optimization: {
minimizer: [
new UglifyJsPlugin({
test: /\.js(\?.*)?$/i,
exclude: /node_modules/
})
]
}
}
optimize-css-assets-webpack-plugin :压缩css样式
const OptimizeCssAssetsWebpackPlugin = require("optimize-css-assets-webpack-plugin")
module.exports = {
plugins: [
new OptimizeCssAssetsWebpackPlugin(),
]
}
imagemin-webpack-plugin :用于压缩图片
const ImageminPlugin = require('imagemin-webpack-plugin').default
module.exports = {
plugins: [
new ImageminPlugin({
test: /\.(jpe?g|png|gif|svg)$/i
})
]
}
webpack 的构建流程是什么
1. 初始化参数: 解析webpack配置参数,合并shell传入和webpack.config.js文件配置的参数,形成最后的配置成果;
2. 开始编译: 上一步得到的参数初始化compiler对象,注册所有配置的插件,插件监听webpack构建生命周期的事件节点,做出相应的反应,执行对象的run方法开始执行编译;
3. 确定入口: 从配置的entry入口,开始解析文件构建AST语法树,找出依赖,递归下去。
4. 编译模块: 递归中根据文件类型和loader配置,调用所有配置的loader对文件进行转换,再找出该模块依赖的模块,再递归本步骤直到所有入口依赖的文件都经过了本步骤的处理。
5. 完成模块编译并输出: 递归完事后,得到每个文件结果,包含每个模块以及他们之间的依赖关系,根据entry或分包配置生成代码块chunk;
6. 输出完成: 输出所有的chunk到文件系统;
webpack 的热更新原理
其实是自己开启了express应用,添加了对webpack编译的监听,添加了和浏览器的websocket长连接,当文件变化触发webpack进行编译并完成后,会通过socket告诉浏览器准备刷新。而为了减少刷新的代价,就是不用刷新页面,而是刷新某个模块,webpack-dev-server可以支持热更新,通过生成文件的hash来对比需要更新的模块,浏览器再进行热替换。
webpack 打包的hash是如何生成的
1、webpack生态种存在多种计算hash的方式
- hash
- chunkhash
- contenthash
hash代表每次webpack编译中生成的hash值,所有使用这种方式的文件hash都相同。每次构建都会使webpack计算新的hash。chunkhash基于入口文件及其关联的chunk形成,某个文件的改动只会影响与它关联的chunk的hash,不会影响其他文件的contenthash根据文件内容创建。当文件内容发生变化时,contenthash会发生变化
2、避免相同随机值
webpack在计算hash后分割chunk。产生相同随机值可能是因为这些文件同属于一个chunk,可以将某个文件提到独立的chunk(如放入entry)
webpack插件如何实现
- webpack本质是一个事件流机制,核心模块:tabable(Sync+Async)Hooks构造出 === Compiler(编译)+Compiletion(创建bundles)
- compiler 对象代表了完整的webpack环境配置。这个对象在启动webpack时被一次性建立,并配置好所有可操作的设置,包括options、loader和plugin。当在webpack环境中应用一插件时,插件将收到此compiler对象的引用。可以使它来访问webpack的主环境。
- compilation对象代表了一次性资源版本构建。当运行webpack开发环境中间件时,每当检测到一个文件变化,就会创建一个心的compilation,从而生成一个新的编译资源。一个compilation对象表现了当前的模块资源、编译生成资源、变化的文件、以及被跟踪依赖的状态的信息。compilation对象也提供了很多关键时机的回调,以供插件做自定义处理时选择使用。
- 创建一个插件函数,在其prototype上定义apply方法,制定一个webpack自身的事件钩子。
- 函数内部处理webpack内部实例的特点数据。
- 处理完成后,调用webpack提供的回调函数。
funciton MyWebpackPlugin(){
};
MyWebpackPlugin.prototype.apply = function(){
compiler.pluginCwebpacksEvenHook"function(compiler){
console.log('这是一个插件');
callback()
}
}
webpack 如何实现持久化缓存
- 服务端设置http缓存头:cache-control
- 打包依赖和运行时到不同的chunk,即作为splitChunk,因为他们几乎是不变的
- 延迟加载:使用import()方式,可以动态加载的文件分到独立的chunk,以得到自己的chunkhash
- 保持hash值的稳定:编译过程和文件内通的更改尽量不影响其他文件hash的计算,对于低版本的webpack生成的增量数字id不稳定的问题,可用hashedModuleidsPlugin基于文件路径生成来解决
如何使用webpack来优化前端性能
用webpack优化前端性能是指优化webpack的输出结果,让打包的最终结果在浏览器运行快速高效。
- 压缩代码:删除多余的代码、注释、简化代码的写法等等方式。可以利用
webpack的UglifyJsPlugin
和ParallelUglifyPlugin
来压缩JS文件,利用cssnano(css-loader
)来压缩css。 - 利用CDN加速:在构建过程中,将引用的静态资源路径修改为CDN上对应的路径。可以利用webpack对于output参数和各loader的publicPath参数来修改资源路径。
- Tree Shaking:将代码中永远不会走到的片段删除掉。可以通过启动webpack时追加参数,
optimize-minimize
来实现。 - Code Splitting:将代码按路有维度或者组件分块(chunk),这样做到按需加载,同时可以充分利用浏览器缓存。
- 提供公共第三方库,SplitChunksPlugin插件来进行公共模块抽取,利用浏览器缓存可以长期缓存这些无需频繁变动的公共代码
webpack treeShaking机制的原理
- 又名摇树优化,是一种通过移除多余代码,来优化打包体积的,生成环境默认是开启的。
- 可以在代码不允许的状态下,分析出不需要的代码。
- 利用es6模块的规范:ES6 Module引入静态分析,故而编译的时候正确判断到底加载了哪些模块,静态分析程序流,判断哪些模块和变量未使用或者未引用,然后删除这部分代码。
webpack 常用Loader
- file-loader:把文件输出到一个文件夹中,在代码中通过相对的URL去引用输出的文件
- url-loader:和file-loader类似,但是能在文件很小的情况下以base64的方式把文件内容注入到代码中去
- soucre-map-loader:加载额外的Source Map文件,以方便断点调试
- image-loader:加载并且压缩图片文件
- babel-loader:把ES6转换成ES5
- css-loader:加载css,支持模块化、压缩、文件导入等特性
- style-loader:把css代码注入到JavaScript中,通过DOM操作去加载css
- eslint-loader:通过ESlint检查JavaScript代码