npx webpack
webpack -> config -> 打包入口 输出目录 -> 入口文件
-> 分析是否有依赖,以及模块的路径 -> 解析处理的内容(es6 + es5)
-> chunkcode 缺失函数,require exports
(function() {// 缺失函数补齐requireeval(chunkcode)exports)({// 依赖模块, 入口模块的路径为key// key: 模块的处理后的chunkcode})// simple-webpack// webpack.config.js// entry// output// mode// Lib// webpack.js// Webpack class// run// 入口文件的路径// 分析文件的内容// 模块依赖路径,内容处理,chunkcode// 递归处理所有依赖, index.js > a.js > b.js// 生成bundle结构,生成文件,放入dist目录// bundle.js// 引入 lib/webpack.js// 引入 webpack options// complier = Webpack(config)// Compiler.run()
const fs = require('fs')const path = require('path')const parser = require('@babel/parser')const traverse = require('@babel/traverse').defaultconst { transformFromAst } = require('@babel/core')module.exports = class Webpack {constructor(options) {this.entry = options.entrythis.output = options.outputthis.modules = []}run() {let info = this.parse(this.entry)this.modules.push(info);for (let i = 0; i < this.modules.length; i++) {let item = this.modules[i]let { dependencies } = item;if (dependencies) {for (let key in dependencies) {this.modules.push(this.parse(dependencies[key]))}}}let obj = {}this.modules.forEach(item => {obj[item.entryFile] = {code: item.code,dependencies: item.dependencies}})this.file(obj)}file(code) {let newCode = JSON.stringify(code);let bundle = `(function(modules){function require(module) {function newRequire(relativePath) {return require(modules[module].dependencies[relativePath])}var exports = {};(function(require,exports,code){eval(code)})(newRequire, exports, modules[module].code)return exports;}require('${this.entry}')})(${newCode})`let distPath = path.join(this.output.path, this.output.filename);fs.writeFileSync(distPath, bundle, 'utf-8');}parse(entryFile) {let content = fs.readFileSync(entryFile, 'utf-8')let ast = parser.parse(content, {sourceType: 'module'})let dependencies = {}traverse(ast, {ImportDeclaration({ node }) {dependencies[node.source.value] = './' + path.join(path.dirname(entryFile), node.source.value)}})let { code } = transformFromAst(ast, null, {presets: ['@babel/preset-env']})return {entryFile,code,dependencies,}}}
