webpack机制
栏目: JavaScript · 发布时间: 5年前
内容简介:以下仅为个人粗略总结和代码,看不懂的稍加理解,本文主要用做个人记录。核心代码如下:
简介
以下仅为个人粗略总结和代码,看不懂的稍加理解,本文主要用做个人记录。
先大致总结一下
- 1.从哪里开始: webpack根据入口模块开始。
- 2.如何进行: 递归读取每个文件,会形成一个依赖列表,依赖列表的,依赖列表是一个以文件相对路径为key,文件内容为value的对象。
- 3.如何处理: 对于每个文件会通过AST解析语法树,返回源码。
- 4.loader在哪: loader是何时何地进行处理?它是在读取文件的时候开始起作用,通过正则匹配文件是否需要处理。然后读取配置文件的loader配置,然后通过递归的方式处理文件。
- 5. Plugins呢: plugins是在合适的时机开始工作,那么这个合适时机如何控制呢,是通过 tapable 事件流机制,实现发布订阅模式。
- 6.最后: 最后返回的是一个匿名自执行函数,定义了一个 webpack__require 方法,解析传入的依赖列表,递归执行。
然后看下代码
核心代码如下:
//入口文件webpack.js #! /usr/bin/env node //第一步:找到当前执行命令的路径,拿到webpack.config.js let path = require("path") let config = require(path.resolve('webpack.config.js')) console.log(path.resolve(),'resolve--------------->') let Compiler = require('../lib/Compiler') let compiler = new Compiler(config) //标识运行编译 compiler.run()
//Compiler.js const fs = require('fs') const path = require('path') const babylon = require('babylon') const travere = require('@babel/traverse').default const t = require('@babel/types') const generator = require('@babel/generator').default const ejs = require('ejs') const {SyncHook} = require('tapable') //babylon把源码转为AST //@babel/traverse //@babel/generator //@babel/types class Compiler { constructor(config) { this.config = config //保存入口文件路径 this.entryID = '' //主模块入口路径 this.modules = {} //存放模块依赖关系 this.entry = config.entry //入口路径 this.root = process.cwd() //当前工作目录 this.hooks = { entryOption: new SyncHook(), compile: new SyncHook(), afterCompile: new SyncHook(), afterPlugins: new SyncHook(), run: new SyncHook(), emit: new SyncHook(), done: new SyncHook(), } //如果传递了plugins参数 let plugins = this.config.plugins if(Array.isArray(plugins)) { plugins.forEach(plugin => { plugin.apply(this) }) } } run() { //执行,并创建模块的依赖关系 this.buildModule(path.resolve(this.root, this.entry), true) //发射一个文件,就是打包后的文件 this.emitFile() } //构建模块 buildModule(modulePath, isEntry) { //首先读取入口文件 let source = this.getSource(modulePath) //模块的ID = this.root - modulePath let moduleName = './' + path.relative(this.root, modulePath) if(isEntry) { this.entryID = moduleName //保存入口名字 } //解析,需要把source源码进行改造,返回一个依赖列表 let {sourceCde, dependencies } = this.parse(source, path.dirname(moduleName)) this.modules[moduleName] = sourceCde dependencies.forEach(dep => { //附模块的递归加载 this.buildModule(path.join(this.root, dep), false) }) } //解析源码, AST解析语法树 parse(source, parentPath) { // console.log(source, parentPath) let ast = babylon(source) let dependencies = [] //依赖数组 travere(ast, { CallExpression() { let node = p.node if(node.callee.name === 'require') { node.callee.name = '_webpack_require_' let moduleName = node.arguments[0].value //这里就是引用模块的名字 moduleName = moduleName + (path.extname(moduleName) ? '' : '.js') moduleName = './' + path.join(parentPath, moduleName) //'src/a.js' dependencies.push(moduleName) node.arguments = [t.stringLiteral(moduleName)] } } }) let sourceCode = generator(ast).code return {sourceCode, dependencies} } //公用读文件的方法 getSource(modulePath) { let content = fs.readFileSync(modulePath, 'utf8') let rules = this.config.module.rules //拿到规则 //拿到每个规则来处理 for(let i=0; i<rules.length; i++) { let rule = rules[i] let { test, use } = rule let len = use.length - 1 if(test.test(modulePath)) { //这个模块需要通过loader转换 function normalLoader() { let loader = require(use[len]) //获取对应loader函数 content = loader(content) //递归调用loader if(len >= 0) { normalLoader() } } normalLoader() } } return content } //发射文件 emitFile() { //用数据 渲染我们的 //拿到输出到哪个目录下 let main = path.join(this.config.output.path, this.config.output.filename) //模板路径 let templateStr = this.getSource(path.join(__dirname, 'main.ejs')) let code = ejs.render(templateStr, {entryId: this.entryID, modules: this.modules}) this.assets = { //资源中路径对应的代码 } this.assets[main] = code fs.writeFileSync(main, this.assets[main]) } } module.exports = Compiler
以上所述就是小编给大家介绍的《webpack机制》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- 快速失败机制 & 失败安全机制
- JavaScript线程机制与事件机制
- 区块链是怎样将分布式组网机制、合约机制、共识机制等技术结合并应用
- Java内存机制和GC回收机制-----笔记
- javascript垃圾回收机制 - 标记清除法/引用计数/V8机制
- Android 8.1 源码_机制篇 -- 全面解析 Handler 机制(原理篇)
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Redis开发与运维
付磊、张益军 / 机械工业出版社 / 2017-3-1 / 89.00
本书全面讲解Redis基本功能及其应用,并结合线上开发与运维监控中的实际使用案例,深入分析并总结了实际开发运维中遇到的“陷阱”,以及背后的原因, 包含大规模集群开发与管理的场景、应用案例与开发技巧,为高效开发运维提供了大量实际经验和建议。本书不要求读者有任何Redis使用经验,对入门与进阶DevOps的开发者提供有价值的帮助。主要内容包括:Redis的安装配置、API、各种高效功能、客户端、持久化......一起来看看 《Redis开发与运维》 这本书的介绍吧!