npm link

npm link

说明

npm link: 本地调试 npm 模块

image.png

npm-sum (npm包)

项目结构

mkdir npm-sum
npm init -y
touch index.js
复制代码
//index.js
const sum = (...args) => {
  return args.reduce((prev, next) => prev + next, 0)
}
module.exports = sum

复制代码

npm link

方式将本地开发包链接到全局 node_modules/下

image.png

报错

权限问题

1629165545(1).png

解决方法,用管理员权限打开power shell

image.png

example (测试项目)

项目结构

mkdir example
npm init -y
touch index.js
复制代码
//index.js
const sum = require('npm-sum')
console.log(sum(1, 2, 3, 4, 5))
复制代码

npm link npm-sum

安装本地npm包(npm-sum),到自己的项目下,会生成在node_modules

运行项目

node index.js
复制代码

image.png

与npm-sum解除关联

npm unlink npm-sum
复制代码

image.png

参考

如何使用 npm-link

原生webpack

最简单的webpack怎么运行的

目录结构

1629167336(1).png

初始化

npm init -y
cnpm install webpack webpack-cli -D
复制代码

src

// src/base/b.js

module.exports = 'b'
复制代码
// src/a.js

let b = require('./base/b.js')
module.exports = 'a' + b
复制代码
// src/index.js

let str = require('./a.js')
console.log(str)
复制代码

webpack.config.js

// webpack.config.js

const path = require('path')
module.exports = {
  mode: 'development',
  entry: './src/index.js',
  output: {
    filename: 'bundle.js',
    path: path.resolve(__dirname, 'dist')
  },
  module: {},
  plugins: []
}
复制代码

运行

根目录下运行命令

webpack
复制代码

image.png

浏览器中查看

// index.html

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <script src="https://juejin.cn/post/bundle.js"></script>
  </body>
</html>

复制代码

实现自己的webpack

1629172500(1).jpg

初始化

webpack-dev(项目)

mkdir webpack-dev
npm init -y
复制代码

zf-pack(类似webpack的npm包)

mkdir zf-pack
npm init -y
复制代码

修改package.json

//package.json

{
  "name": "zf-pack",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  //新增
  "bin": {
    "zf-pack": "./bin/zf-pack.js"
  }
}
复制代码

新增bin

bin/zf-pack.js

#! /usr/bin/env node
console.log('start')
复制代码

关联运行

zf-pack

cd zf-pack //管理员权限
npm link
复制代码

webpack-dev

npm link zf-pack
npx zf-pack
复制代码

image.png

zf-pack拿到webpack-dev中的代码

webpack-dev

webpack.config.js

// webpack.config.js

const path = require('path')
module.exports = {
  mode: 'development',
  entry: './src/index.js',
  output: {
    filename: 'bundle.js',
    path: path.resolve(__dirname, 'dist')
  },
  module: {},
  plugins: []
}
复制代码

src目录

// src/base/b.js

module.exports = 'b'
复制代码
// src/a.js

let b = require('./base/b.js')
module.exports = 'a' + b
复制代码
// src/index.js

let str = require('./a.js')
console.log(str)
复制代码

zf-pack

bin

// /bin/zf-pack.js

#! /usr/bin/env node
// console.log('start')
let path = require('path')

// // config配置文件
let config = require(path.resolve('webpack.config.js'))

let Compiler = require('../lib/Compiler.js')
let compiler = new Compiler(config)

// 标识运行编译
compiler.run()
复制代码

lib

// lib/Compiler.js

let fs = require('fs')
let path = require('path')

class Compiler {
  constructor (config) {
    // entry output
    this.config = config
    // 需要保存入口文件的路径
    this.entryId // './src/index.js'
    // 需要保存所有的模块依赖
    this.modules = {}
    this.entry = config.entry // 入口路径
    // 工作路径
    this.root = process.cwd()
  }
  getSource (modulePath) {
    let content = fs.readFileSync(modulePath, 'utf8')
    return content
  }
  buildModule (modulePath, isEntry) {
    let source = this.getSource(modulePath)
    // 模块id modulePath  = modulePath- this.root  src/index.js
    let moduleName = './' + path.relative(this.root, modulePath)
    console.log('source', source)
    console.log('moduleName', moduleName)
  }
  run () {
    this.buildModule(path.resolve(this.root, this.entry), true)
  }
}
module.exports = Compiler
复制代码

重新发布运行

zf-pack

npm link
复制代码

webpack-dev

npm link zf-pack
npx zf-pack
复制代码

image.png

AST递归解析

安装依赖

cnpm install babylon @babel/types @babel/traverse @babel/generator -S
复制代码

增加parse方法

let fs = require('fs')
let path = require('path')
let babylon = require('babylon')
let t = require('@babel/types')
let traverse = require('@babel/traverse').default
let generator = require('@babel/generator').default

class Compiler {
  constructor (config) {
    // entry output
    this.config = config
    // 需要保存入口文件的路径
    this.entryId // './src/index.js'
    // 需要保存所有的模块依赖
    this.modules = {}
    this.entry = config.entry // 入口路径
    // 工作路径
    this.root = process.cwd()
  }
  getSource (modulePath) {
    let content = fs.readFileSync(modulePath, 'utf8')
    return content
  }
  parse (source, parentPath) {
    let ast = babylon.parse(source)
    let dependencies = [] // 依赖的数组
    traverse(ast, {
      CallExpression (p) {
        //  a() require()
        let node = p.node // 对应的节点
        if (node.callee.name === 'require') {
          node.callee.name = '__webpack_require__'
          let moduleName = node.arguments[0].value // 取到的就是模块的引用名字
          moduleName = moduleName + (path.extname(moduleName) ? '' : '.js')
          moduleName = './' + path.join(parentPath, moduleName)
          ;('src/a.js')
          dependencies.push(moduleName)
          node.arguments = [t.stringLiteral(moduleName)]
        }
      }
    })
    let sourceCode = generator(ast).code
    return { sourceCode, dependencies }
  }
  buildModule (modulePath, isEntry) {
    let source = this.getSource(modulePath)
    // 模块id modulePath  = modulePath- this.root  src/index.js
    let moduleName = './' + path.relative(this.root, modulePath)
    if (isEntry) {
      this.entryId = moduleName // 保存入口的名字
    }
    // 解析需要把source源码进行改造 返回一个依赖列表
    let { sourceCode, dependencies } = this.parse(
      source,
      path.dirname(moduleName)
    ) // ./src
    console.log(sourceCode, dependencies)
    // 把相对路径和模块中的内容 对应起来
    this.modules[moduleName] = sourceCode

    dependencies.forEach(dep => {
      // 附模块的加载 递归加载
      this.buildModule(path.join(this.root, dep), false)
    })
  }
  run () {
    this.buildModule(path.resolve(this.root, this.entry), true)
  }
}
module.exports = Compiler

复制代码

运行

1629181689(1).jpg

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享