美文网首页
用js写一个模块打包工具

用js写一个模块打包工具

作者: 月_关 | 来源:发表于2021-05-27 10:34 被阅读0次
# 概览
1. 找到入口文件
2. 解析入口文件, 提取它依赖的文件
3. 解析入口文件的依赖的依赖, 递归去创建一个文件间的依赖图, 描述所有文件的依赖关系
4. 把所有文件打包成一个文件

## 开发

1. 新建几个js文件
* name.js
* message.js
* entry.js

2. 三个文件依赖关系
entry 依赖-> message 依赖-> name

3. 创建一个my-webpack.js 我们在这个文件开发

4.了解几个工具库
* babylon 生成ast语法树
* babel-traverse 遍历ast语法树
* babel-core 提取语法树里面的代码

5. 创建一个打包命令在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))

相关文章

  • 用js写一个模块打包工具

  • webpack讲解

    1,什么是webpack webpack 本质上来说,是一个现代js应用的静态模块打包工具 重点:模块,打包 模块...

  • webpack学习笔记(踩坑笔记)

    认识webpack webpcak是基于JS应用的前端模块化打包工具,强调模块化(核心)和打包。流行打包工具:we...

  • webpack简介与核心概念

    【介绍】 现代 JavaScript 应用程序的静态模块打包工具,能够递归构建一个js模块的依赖关系,将模块最终打...

  • 前端面试攻略

    1.webpack和gulp看法 webpack是一个模块打包工具,可以管理和打包html,js,css以及各种静...

  • webpack

    webpack是什么? webpack将静态资源称之为模块。webpack是一个模块打包工具,可以兼容多种js书写...

  • webpack and Babel

    webpack 简单来说是一个 module bundler,把很多模块打包成一个 bundle.js 的工具。 ...

  • 1.webpack定义

    一.核心定义:模块打包工具 包括ES Module/CommonJS/CMD/AMD 模块不当只是js文件还有h...

  • 前端构建工具&&前端模块化工具&&前端架构工具&&前端类库

    前端自动化构建工具 webpack 是一个打包模块化的js的工具,在webpack里一切文件都是模块,通过load...

  • Vue2.0基础-vue-cli搭建项目

    一、什么是webpack? webpack是一个module bundler(模块打包工具),其可以兼容各种js书...

网友评论

      本文标题:用js写一个模块打包工具

      本文链接:https://www.haomeiwen.com/subject/jbursltx.html