用js寫一個模塊打包工具

# 概覽
1. 找到入口文件
2. 解析入口文件, 提取它依賴的文件
3. 解析入口文件的依賴的依賴, 遞歸去創(chuàng)建一個文件間的依賴圖, 描述所有文件的依賴關(guān)系
4. 把所有文件打包成一個文件

## 開發(fā)

1. 新建幾個js文件
* name.js
* message.js
* entry.js

2. 三個文件依賴關(guān)系
entry 依賴-> message 依賴-> name

3. 創(chuàng)建一個my-webpack.js 我們在這個文件開發(fā)

4.了解幾個工具庫
* babylon 生成ast語法樹
* babel-traverse 遍歷ast語法樹
* babel-core 提取語法樹里面的代碼

5. 創(chuàng)建一個打包命令在package.json
"scripts": {
    "build": "rm -rf dist.js && node my-webpack.js > dist.js"
  }
const fs = require('fs')
const babylon = require('babylon')
const path = require('path')
const traverse = require('babel-traverse').default
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 mainAsset = createAsset(entry)
  const allAsset = [mainAsset]
  for (let asset of allAsset) {
    const dirname = path.dirname(asset.filename) // 獲取絕對路徑
    asset.mapping = {} // 當前文件的依賴對象, key:路徑, 值是id
    asset.dependencies.forEach(relativePath => {
      const absolutePath = path.join(dirname, relativePath) // 依賴文件的絕對路徑
      // 獲取文件的依賴
      const childAsset = createAsset(absolutePath)

      asset.mapping[relativePath] = childAsset.id

      allAsset.push(childAsset) // 遍歷整個依賴圖
    })
  }
  return allAsset
}

function bundle (graph) {
  let modules = ''

  graph.forEach(module => {
    modules += `${module.id}:[
      function (require, module, exports) {
        ${module.code}
      },
      ${JSON.stringify(module.mapping)}
    ],`
  })

  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')

console.log(bundle(graph))
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 平臺:Windows 7 版本:1.7.7 簡介 Sea.js實現(xiàn)了對JS代碼的模塊化組織,大大提高了前端開發(fā)效率...
    逸之閱讀 4,607評論 1 4
  • webpack 支持 AMD 和 CommonJS 類型,通過 loader 機制也可以使用 ES6 的模塊格式,...
    賽亞人之神閱讀 205評論 0 0
  • 1.模塊回顧 模塊化為了解決什么? 主要是為了解決變量污染的問題,以及便于維護,以及重用 什么是模塊?模塊化? 模...
    moly琴閱讀 317評論 0 0
  • 1. 簡介 介紹模塊打包工具 2. 什么是模塊 關(guān)于模塊和模塊化,百度百科有一段引用自《Java應(yīng)用架構(gòu)設(shè)計:模塊...
    love丁酥酥閱讀 306評論 0 1
  • 表情是什么,我認為表情就是表現(xiàn)出來的情緒。表情可以傳達很多信息。高興了當然就笑了,難過就哭了。兩者是相互影響密不可...
    Persistenc_6aea閱讀 129,959評論 2 7

友情鏈接更多精彩內(nèi)容