文章目录
- webpack打包流程
- webpack声明周期
- 自开发 webpack 插件
- loader和plugin的区别
- Loader(加载器):
- Plugin(插件):
- 总结区别:
- webpack如何热启动及原理
- HMR(热更新实现的原理)
- websocket
- fs.watch
- 说说一些常用的loader和plugin
- 常用Loader:
- 常用Plugin:
- webpack和vite的区别
- 1. **构建速度:**
- 2. **开发服务器:**
- 3. **构建输出:**
- 4. **配置方式:**
- 5. **生态系统:**
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 插件
class MyPlugin {// 构造函数可以接收配置选项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就会被应用。
- Loader通过Webpack配置中的
-
示例:
- 以下是一个使用Babel Loader将ES6代码转换为ES5的Webpack配置示例:
module.exports = {module: {rules: [{test: /\.js$/,exclude: /node_modules/,use: {loader: 'babel-loader',},},],}, };
- 以下是一个使用Babel Loader将ES6代码转换为ES5的Webpack配置示例:
Plugin(插件):
-
作用:
- Plugin用于执行在整个构建过程中的特定任务,例如代码优化、资源管理、环境变量注入等。插件可以在Webpack的不同生命周期中执行,提供了更广泛的自定义和扩展能力。
-
配置:
- 插件通过Webpack配置中的
plugins
数组进行配置。每个插件通常是一个JavaScript对象,配置了插件的行为和选项。
- 插件通过Webpack配置中的
-
示例:
- 以下是一个使用
HtmlWebpackPlugin
插件自动生成HTML文件的Webpack配置示例:const HtmlWebpackPlugin = require('html-webpack-plugin');module.exports = {plugins: [new HtmlWebpackPlugin({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: new webpack.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: [new webpack.HotModuleReplacementPlugin(),],
};
HMR(热更新实现的原理)
- 变更检测
Webpack使用 Node.js 中的 fs 模块来实现文件系统的监视。Node.js的 fs 模块提供了一种监听文件和目录变化的方式,即 fs.watch 或 fs.watchFile。 - 重新打包
将变更的文件从新执行解析,编译,打包,形成输出文件,并发送给HMR。 - 通知客户端
HMR 通过 websocket(在初始打包时就已经建立),向客户端发送要更新文件的信息 - 浏览器更新
浏览器拿到新打包好的文件后,会保存当前页面的状态,替换掉旧的模块。
websocket
// 执行上面语句之后,客户端就会与服务器进行连接。
var ws = new WebSocket("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: [new HtmlWebpackPlugin({template: './src/index.html',// 其他配置...}), ]
-
MiniCssExtractPlugin: 将CSS从JS文件中提取出来,生成单独的CSS文件。
const MiniCssExtractPlugin = require('mini-css-extract-plugin');plugins: [new MiniCssExtractPlugin({filename: '[name].css',chunkFilename: '[id].css',}), ]
-
CleanWebpackPlugin: 在每次构建前清理输出目录。
const { CleanWebpackPlugin } = require('clean-webpack-plugin');plugins: [new CleanWebpackPlugin(), ]
-
DefinePlugin: 允许在编译时创建全局常量。
const webpack = require('webpack');plugins: [new webpack.DefinePlugin({'process.env.NODE_ENV': JSON.stringify('production'),}), ]
-
HotModuleReplacementPlugin: 热更新
plugins: {HotModuleReplacementPlugin: new webpack.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可能提供更简单、更快速的开发体验。