实现一个简易版webpack
Posted amiezhang
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了实现一个简易版webpack相关的知识,希望对你有一定的参考价值。
现实 webpack 的打包产物
大概长这样(只把核心代码留下来):
实现一个简版的webpack
依葫芦画瓢,实现思路分2步:
1. 分析入口文件,把所有的依赖找出来(包括所有后代的依赖)
2. 拼接出类似上面的立即执行函数
找依赖
const fs = require(‘fs‘); const path = require(‘path‘); const parser = require(‘@babel/parser‘); const traverse = require(‘@babel/traverse‘).default; const transformFromAST = require(‘@babel/core‘); // 分析一个文件,转成CommonJS Module,并找出它的依赖 function readCode(filePath) // 读取文件字符串 const content = fs.readFileSync(filePath, ‘utf-8‘); // 语法解析成 AST const ast = parser(content, sourceType: ‘module‘ ) // 获取本文件的依赖 const dependiences = []; // 遍历 AST,每当触发依赖钩子,就往依赖数组添加 traverse(ast, ImportDeclaration(node) // 把对应的以来路径存起来 dependiences.push(node.source.value) ) // 把 es6 转成 es5 字符串 // 最重要的是把 esModule 的 import export,转成 es5 能认识的 commonJs写法 const code = transformFromAST(ast, null, presets: [‘@babel/preset-env‘] ) return filePath, code, dependiences // 广度优先算法,深入找出所有的依赖 function getAllDependencies(filePath) const entryObj = readCode(filePath); const dependencies = [entryObj]; for (const dependency of dependencies) const curDirname = path.dirname(dependency.filePath) for (const relativePath dependency.dependencies) const absolutePath = path.join(curDirname, relativePath); const child = readCode(absolutePath); child.relativePath = relativePath; dependencies.push(child); return dependencies;
ps: 我们用的是babel的配套工具来做语法分析和转化,但是真正的webpack用的是webassemblyjs的配套工具
拼写立即执行函数
function bundle(fileName) const dependencies = getAllDependencies(fileName); const modulesStr = ‘‘; dependencies.forEach(dependency => const key = dependency.relativePath || dependency.filePath; modulesStr += `‘$key‘: function(module, exports, require) $ dependency.code ` ) return `(function(modules) const installedModules = ; function require(id) // 解决循环依赖 if (installedModules[id]) return installedModules[id].exports; var module = installedModules[id] = exports: ; modules[id].call(module.exports, module, module.exports, require); return module.exports; return require(‘$fileName‘) )($modulesStr)`
以上是关于实现一个简易版webpack的主要内容,如果未能解决你的问题,请参考以下文章