文件结构
测试代码
如下,source文件夹下的是测试代码
// entry.js
import message from './message.js'
console.log(message)
//message.js
import {name} from './name.js'
export default `${name} is a girl`
// name.js
export const name = 'lily'
mywebpack.js是模拟webpack实现的代码
// mywebpack.js
const fs = require('fs')
const babylon = require('babylon')
const traverse = require('babel-traverse').default;
const path = require('path');
const babel = require('babel-core');
let ID = 0
function createAsset(filename){
const content = fs.readFileSync(filename,'utf-8');
const ast = babylon.parse(content,{sourceType:'module'})
const dependencies = []
traverse(ast,{ImportDeclaration:({node})=>{
dependencies.push(node.source.value)
}})
const id = ID++
const {code} = babel.transformFromAst(ast,null,{presets:['env']})
return {
id,
filename,
dependencies,
code,
}
}
function createGraph(entry){
const mainAssets = createAsset(entry)
const allAssets = [mainAssets]
for(let asset of allAssets){
const dir = path.dirname(asset.filename)
asset.mapping = {}
asset.dependencies.length>0&&asset.dependencies.forEach(relativePath=>{
const absolutePath = path.join(dir,relativePath)
const childAsset = createAsset(absolutePath)
asset.mapping[relativePath] = childAsset.id
allAssets.push(childAsset)
})
}
return allAssets
}
function boundle(graph) {
let modules = ''
graph.forEach((module)=>{
modules+=`${module.id}:[
function(require,module,exports){
${module.code}
},
${JSON.stringify(module.mapping)}
],`
})
// 这里require,exports.default,需要深入了解一下commonjs规范
const result = `
(function(modules){
function require(id){
const [fn,mapping] = modules[id]
function localRequire(relativePath){
return require(mapping[relativePath])
}
const module = {exports:{}}
fn(localRequire, module, module.exports)
return module.exports
}
require(0)
})({${modules}})
`
return result
}
const graph = createGraph('./source/entry.js')
const result = boundle(graph)
console.log(result)
快捷命令编译
package.json的script中新增build命令
"build": "rm -f dist.js && node mywebpack.js > dist.js"