文章目录
webpack打包流程
- 解析配置文件:Webpack 会读取并解析配置文件(通常是 webpack.config.js 文件),并根据配置生成一个 Compiler 对象。
- 读取入口文件:Webpack 根据配置中的入口文件,读取这些文件及其依赖的模块,并将它们组成一个依赖图。
- 解析模块依赖:Webpack 会根据模块之间的依赖关系,递归地解析它们的依赖,直到所有的依赖都被解析完毕。
- 加载模块:Webpack 会根据模块的路径,使用相应的 Loader 加载模块的源代码,并将其转换为 Webpack 可以处理的形式。
- 转换代码:Webpack 会根据配置中的插件,对加载的模块进行一系列的转换操作,比如压缩、合并、优化等。
- 生成代码:Webpack 会将所有模块转换后的代码合并成一个或多个文件,并输出到指定的输出目录中。
webpack声明周期
在 Webpack 打包的过程中,Webpack 会触发一系列的生命周期事件。这些事件可以被插件所监听,并在相应的时机执行插件的逻辑。
Webpack 生命周期的主要事件包括:
- beforeRun:Webpack 进入编译前的阶段,此时会初始化 Compiler 对象。
- run:Webpack 开始编译前的阶段,此时会读取入口文件和依赖,并创建依赖图。
- compilation:Webpack 进入编译阶段,此时会开始编译入口文件和依赖的模块,并生成输出文件。
- emit:Webpack 生成输出文件前的阶段,此时可以在插件中处理生成的输出文件。
- done:Webpack 完成打包后的阶段,此时可以在插件中进行一些清理工作。
自开发 webpack 插件
classMyPlugin{// 构造函数可以接收配置选项constructor(options){this.options = options ||{};}// Webpack 会调用 apply 方法来安装插件apply(compiler){
compiler.hooks.done.tap('FileSizePlugin',stats=>{const{ compilation }= stats;const assets = compilation.assets;let size =0;for(let filename in assets){
size += assets[filename].size();}
console.log(`Total size of the generated files: ${size} bytes`);});}}
module.exports = MyPlugin;
loader和plugin的区别
在Webpack中,Loader和Plugin是两个不同的概念,它们分别用于处理不同类型的任务,而且在Webpack的构建过程中扮演不同的角色。
Loader(加载器):
- 作用:- Loader用于在Webpack构建过程中对模块的源代码进行转换,将它们从一种形式转换为另一种形式。主要用于加载和转换文件,如将ES6代码转换为ES5、将SCSS转换为CSS等。
- 配置:- Loader通过Webpack配置中的
module.rules
进行配置。每个规则定义了一组条件和对应的Loader,当模块匹配这些条件时,相应的Loader就会被应用。 - 示例:- 以下是一个使用Babel Loader将ES6代码转换为ES5的Webpack配置示例:
module.exports ={module:{rules:[{test:/\.js$/,exclude:/node_modules/,use:{loader:'babel-loader',},},],},};
Plugin(插件):
- 作用:- Plugin用于执行在整个构建过程中的特定任务,例如代码优化、资源管理、环境变量注入等。插件可以在Webpack的不同生命周期中执行,提供了更广泛的自定义和扩展能力。
- 配置:- 插件通过Webpack配置中的
plugins
数组进行配置。每个插件通常是一个JavaScript对象,配置了插件的行为和选项。 - 示例:- 以下是一个使用
HtmlWebpackPlugin
插件自动生成HTML文件的Webpack配置示例:const HtmlWebpackPlugin =require('html-webpack-plugin');module.exports ={plugins:[newHtmlWebpackPlugin({template:'src/index.html',}),],};
总结区别:
- Loader:- 处理模块的源代码转换。- 在
module.rules
中配置。- 针对不同类型的文件进行处理。 - Plugin:- 执行整个构建过程中的特定任务。- 在
plugins
中配置。- 提供了更广泛的自定义和扩展能力。
在实际的Webpack配置中,Loader和Plugin通常一起使用,以满足对不同类型的文件和构建过程的灵活需求。Loader负责处理文件转换,而Plugin负责执行其他构建任务。
webpack如何热启动及原理
需要安装
webpack-dev-server
npm install webpack webpack-dev-server --save-dev
设置 HotModuleReplacementPlugin,HotModuleReplacementPlugin 是 webpack 是自带的
plugins:{HotModuleReplacementPlugin:newwebpack.HotModuleReplacementPlugin()}
再设置一下devServer
devServer:{contentBase: path.resolve(__dirname,'dist'),hot:true,// 重点关注historyApiFallback:true,compress:true}
const webpack =require('webpack');
module.exports ={entry:'./src/index.js',output:{filename:'bundle.js',path:'/dist',},devServer:{contentBase: path.resolve(__dirname,'dist'),hot:true,// 重点关注historyApiFallback:true,compress:true},plugins:[newwebpack.HotModuleReplacementPlugin(),],};
HMR(热更新实现的原理)
- 变更检测 Webpack使用 Node.js 中的 fs 模块来实现文件系统的监视。Node.js的 fs 模块提供了一种监听文件和目录变化的方式,即 fs.watch 或 fs.watchFile。
- 重新打包 将变更的文件从新执行解析,编译,打包,形成输出文件,并发送给HMR。
- 通知客户端 HMR 通过 websocket(在初始打包时就已经建立),向客户端发送要更新文件的信息
- 浏览器更新 浏览器拿到新打包好的文件后,会保存当前页面的状态,替换掉旧的模块。
websocket
// 执行上面语句之后,客户端就会与服务器进行连接。var ws =newWebSocket("wss://echo.websocket.org");// 实例对象的 onopen 属性,用于指定连接成功后的回调函数
ws.onopen=function(evt){
console.log("Connection open ...");
ws.send("Hello WebSockets!");};// 实例对象的 onmessage 属性,用于指定收到服务器数据后的回调函数。可以接受二进制数据,blob 对象或者 Arraybuffer 对象
ws.onmessage=function(evt){
console.log("Received Message: "+ evt.data);
ws.close();};// 实例对象的 onclose 属性,用于指定连接关闭后的回调函数。
ws.onclose=function(evt){
console.log("Connection closed.");};
上面通过
new Websocket
创建一个客户端与服务端通信的实例,并通过
onmessage
属性,接受指定服务器返回的数据,并进行相应的处理。
热更新是服务器更新后向客户端发送新的数据并要求客户端更新,而websocket最大的特点就是 服务器可以主动向客户端推送消息,客户端也可以主动向服务器发送信息。这是 HTTP 不具备的,热更新实际上就是服务器端的更新通知到客户端,所以选择了 Websocket。
fs.watch
const fs =require('fs');// 监听文件变化const watcher = fs.watch('./src',(event, filename)=>{
console.log(`File ${filename} has been ${event}`);});// 在程序退出时关闭观察器
process.on('exit',()=>{
watcher.close();});
说说一些常用的loader和plugin
Webpack有许多常用的loader和plugin,它们扩展了Webpack的功能,使其能够处理不同类型的文件、优化代码、生成HTML等。以下是一些常用的loader和plugin:
常用Loader:
- babel-loader: 用于将新版本的JavaScript代码转译为向后兼容的版本,以便在旧版本浏览器中运行。
module:{rules:[{test:/\.js$/,exclude:/node_modules/,use:{loader:'babel-loader',},},],}
- style-loader和css-loader: 用于处理CSS文件,style-loader将CSS注入到DOM中,而css-loader负责解析CSS文件中的
@import
和url()
等语句。module:{rules:[{test:/\.css$/,use:['style-loader','css-loader'],},],}
- file-loader和url-loader: 用于处理文件,包括图片、字体等。file-loader将文件复制到输出目录,并返回文件路径,而url-loader可以将小文件转换成DataURL。
module:{rules:[{test:/\.(png|jpg|gif)$/,use:[{loader:'url-loader',options:{limit:8192,// 小于8KB的文件转换为DataURL},},],},],}
常用Plugin:
- HtmlWebpackPlugin: 自动生成一个HTML文件,并将打包后的脚本自动添加到HTML文件中。
const HtmlWebpackPlugin =require('html-webpack-plugin');plugins:[newHtmlWebpackPlugin({template:'./src/index.html',// 其他配置...}),]
- MiniCssExtractPlugin: 将CSS从JS文件中提取出来,生成单独的CSS文件。
const MiniCssExtractPlugin =require('mini-css-extract-plugin');plugins:[newMiniCssExtractPlugin({filename:'[name].css',chunkFilename:'[id].css',}),]
- CleanWebpackPlugin: 在每次构建前清理输出目录。
const{ CleanWebpackPlugin }=require('clean-webpack-plugin');plugins:[newCleanWebpackPlugin(),]
- DefinePlugin: 允许在编译时创建全局常量。
const webpack =require('webpack');plugins:[newwebpack.DefinePlugin({'process.env.NODE_ENV':JSON.stringify('production'),}),]
- HotModuleReplacementPlugin: 热更新
plugins:{HotModuleReplacementPlugin:newwebpack.HotModuleReplacementPlugin()}
webpack和vite的区别
Webpack和Vite都是现代前端开发中常用的构建工具,但它们在设计和使用上有一些显著的区别。以下是Webpack和Vite之间的一些主要区别:
1. 构建速度:
- Webpack: Webpack是一个强大的打包工具,但在初次构建时可能会比较慢,特别是在大型项目中。Webpack通过使用多个loader和plugin来处理各种任务,这可能导致构建时间较长。
- Vite: Vite致力于提供更快的开发和构建速度。它利用了现代浏览器原生支持的ES模块特性,实现了快速的开发服务器和快速的生产构建。Vite在开发过程中使用原生ES模块,无需打包,因此启动速度非常快。
2. 开发服务器:
- Webpack: Webpack的开发服务器通常需要一些时间来启动,因为它需要构建整个应用程序。它在开发中通常使用HMR(热模块替换)来提高开发体验。
- Vite: Vite使用了基于ES模块的开发服务器,不需要构建整个应用,因此启动速度非常快。Vite还支持更细粒度的HMR,使得只更新修改的部分而不影响整个应用。
3. 构建输出:
- Webpack: Webpack在生产构建时生成的代码通常较大,因为它会将所有模块打包成一个或多个文件,包含了一些运行时的代码。
- Vite: Vite的生产构建输出更为精简,因为它支持按需导入,只生成实际用到的模块,减小了打包文件的体积。
4. 配置方式:
- Webpack: Webpack的配置相对较复杂,需要详细配置loader、plugin、entry等参数,适用于更灵活的场景。
- Vite: Vite的配置相对简单,尤其是对于Vue.js项目,因为Vite提供了一套默认配置,无需额外的配置即可快速启动。
5. 生态系统:
- Webpack: Webpack是一个成熟、强大的工具,有着庞大的生态系统和社区支持,适用于各种类型的项目。
- Vite: Vite是一个相对较新的项目,因此生态系统相对较小,但它在Vue.js项目中有着良好的集成。
总体来说,选择Webpack还是Vite取决于项目的具体需求。对于大型项目或者对灵活性有更高要求的项目,Webpack可能是更好的选择。而对于中小型项目,尤其是Vue.js项目,Vite可能提供更简单、更快速的开发体验。
版权归原作者 可缺不可滥 所有, 如有侵权,请联系我们删除。