webpack 编译流程
- 初始化参数:从配置文件和 Shell 语句中读取并合并参数,得出最终的配置对象
- 用上一步得到的参数初始化 Compiler 对象
- 加载所有配置的插件
- 执行对象的 run 方法开始执行编译
- 根据配置中的entry找出入口文件
- 从入口文件出发,调用所有配置的Loader对模块进行编译
- 再找出该模块依赖的模块 , 再递归本步骤直到所有入口依赖的文件都经过了本步骤的处理
- 根据入口和模块之间的依赖关系 , 组装成一个个包含多个模块的 Chunk
- 再把每个 Chunk 转换成一个单独的文件加入到输出列表
- 在确定好输出内容后 , 根据配置确定输出的路径和文件名 , 把文件内容写入到文件系统
在以上过程中 , Webpack 会在特定的时间点广播出特定的事件 , 插件在监听到感兴趣的事件后会执行特定的逻辑 , 并且插件可以调用 Webpack 提供的 API 改变 Webpack 的运行结果
文章插图
1.1entry?srcentry1.js
let title = require("./title")console.log("entry12", title)
srcentry2.jslet title = require("./title.js")console.log("entry2", title)
srctitle.jsmodule.exports = "title"
1.2loader.js?- loader 的本质就是一个函数 , 一个用于转换或者说翻译的函数
- 把那些 webpack 不认识的模块 less sass baxx 转换为 webpack 能认识的模块 js json
【前端面试题-工程化-webpack 编译流程】
function loader1(source) {//let name= 'entry1';return source + "//logger1" //let name= 'entry1';//logger1}module.exports = loader1
loaderslogger2-loader.jsfunction loader2(source) {//let name= 'entry1';return source + "//logger2" //let name= 'entry1';//logger2}module.exports = loader2
1.3 plugin.js?pluginsdone-plugin.jsclass DonePlugin {Apply(compiler) {compiler.hooks.done.tap("DonePlugin", () => {console.log("done:结束编译")})}}module.exports = DonePlugin
pluginsrun1-plugin.jsclass RunPlugin {apply(compiler) {//在此插件里可以监听run这个钩子compiler.hooks.run.tap("Run1Plugin", () => {console.log("run1:开始编译")})}}module.exports = RunPlugin
pluginsrun2-plugin.jsclass RunPlugin {apply(compiler) {compiler.hooks.run.tap("Run2Plugin", () => {console.log("run2:开始编译")})}}module.exports = RunPlugin
1.4 webpack.config.js?webpack.config.jsconst path = require("path")const Run1Plugin = require("./plugins/run1-plugin")const Run2Plugin = require("./plugins/run2-plugin")const DonePlugin = require("./plugins/done-plugin")module.exports = {mode: "development",devtool: false,context: process.cwd,entry: {entry1: "./src/entry1.js",entry2: "./src/entry2.js",},output: {path: path.resolve(__dirname, "dist"),filename: "[name].js",},resolve: {extensions: [".js", ".jsx", ".tx", ".tsx"],},module: {rules: [{test: /.js$/,use: [path.resolve(__dirname, "loaders/loader2.js"), path.resolve(__dirname, "loaders/loader1.js")],},],},plugins: [new DonePlugin(), new Run2Plugin(), new Run1Plugin()],}
1.5debugger.js?debugger.jsconst fs = require("fs")const webpack = require("./webpack2")// const webpack = require("webpack")const webpackConfig = require("./webpack.config")debuggerconst compiler = webpack(webpackConfig)//4.执行`Compiler`对象的 run 方法开始执行编译compiler.run((err, stats) => {if (err) {console.log(err)} else {//stats代表统计结果对象const statsJson = JSON.stringify(stats.toJson({// files: true, //代表打包后生成的文件assets: true, //其实是一个代码块到文件的对应关系chunks: true, //从入口模块出发 , 找到此入口模块依赖的模块 , 或者依赖的模块依赖的模块 , 合在一起组成一个代码块modules: true, //打包的模块 每个文件都是一个模块}))fs.writeFileSync("./statsJson.json", statsJson)}})
1.6 webpack.js?webpack2.jsconst Compiler = require("./Compiler")function webpack(options) {// 1.初始化参数:从配置文件和 Shell 语句中读取并合并参数,得出最终的配置对象//argv[0]是Node程序的绝对路径 argv[1] 正在运行的脚本// node debugger --mode=productionconst argv = process.argv.slice(2)const shellOptions = argv.reduce((shellOptions, options) => {// options = '--mode=development'const [key, value] = options.split("=")shellOptions[key.slice(2)] = valuereturn shellOptions}, {})console.log("shellOptions=>", shellOptions)const finalOptions = { ...options, ...shellOptions }//2.用上一步得到的参数初始化 `Compiler` 对象const compiler = new Compiler(finalOptions)//3.加载所有配置的插件const { plugins } = finalOptionsfor (let plugin of plugins) {//订阅钩子plugin.apply(compiler)}return compiler}module.exports = webpack
推荐阅读
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 单位行贿罪怎么判?
- 王宝强|曝王宝强前经纪人已出狱!前妻正在办理移民,这是要双宿双飞了?
- |曝王宝强前经纪人已出狱!前妻正在办理移民,这是要双宿双飞了?
- 马蓉|曝宋喆提前出狱,马蓉移民后儿子被质疑,王宝强疑为二人铺路出国
- 翟欣欣|“毒妻”翟欣欣隐瞒婚史,41天骗走1300万,逼死前夫,结局如何?
- 周一围|把温柔给了前女友童蕾,把薄情给了朱丹,周一围的爱究竟多奢侈?
- 董子健|新瓜!曝三字离婚男星和二字冷艳小花婚内出轨,前妻是谁引热议!
- 马蓉|曝王宝强前经纪人已出狱!王宝强加强了安保,马蓉则在加紧办理移民手续
- 易烊千玺|易烊千玺:老中青三代集结,同陈道明靳东2位前辈野外骑马踏春游
- 杨幂|港媒曝刘恺威正在筹办婚礼迎娶李晓峰,杨幂过门不入令前公婆震怒