构建纯 js 包用 rollup,如果有 图片样式就要用 webpack 构建.

新建项目 my-vue,新增文件夹 packages

一、初始化package.json

1.执行 yarn init -y

在我们创建的项目下执行 yarn init -y ,生成 package.json 文件
image.png

2.在package.json里配置构建属性

  1. {
  2. "private": true,
  3. "name": "my-vue3",
  4. "version": "1.0.0",
  5. "main": "index.js",
  6. "license": "MIT",
  7. "workspaces": [
  8. "packages/*"
  9. ],
  10. "scripts": {
  11. "dev": "node scripts/dev.js",
  12. "build": "node scripts/build.js"
  13. },
  14. "dependencies": {
  15. "@rollup/plugin-json": "^4.1.0",
  16. "@rollup/plugin-node-resolve": "^13.0.0",
  17. "execa": "^5.1.1",
  18. "rollup": "^2.52.3",
  19. "rollup-plugin-typescript2": "^0.30.0",
  20. "typescript": "^4.3.4"
  21. }
  22. }

私有属性”private”: true,

工作空间:workspaces

配置构建脚本scripts。

3.配置各个包的package.json

在packages 下新建包,并进入到包路径下,执行yarn init -y 生成包的 package.json 文件
image.png

配置包的package.json

  1. {
  2. "name": "@vue/reactivity",
  3. "version": "1.0.0",
  4. "main": "index.js",
  5. "module": "dist/reactivity.esm-bundler.js",
  6. "license": "MIT",
  7. "buildOptions":{
  8. "name":"VueReactivity",
  9. "formats":[
  10. "cjs",
  11. "global",
  12. "esm-bundler"
  13. ]
  14. }
  15. }
  1. {
  2. "name": "@vue/shared",
  3. "version": "1.0.0",
  4. "main": "index.js",
  5. "module": "dist/shared.esm-bundler.js",
  6. "license": "MIT",
  7. "buildOptions":{
  8. "name":"VueShared",
  9. "formats":[
  10. "cjs",
  11. "esm-bundler"
  12. ]
  13. }
  14. }

name

是每个包的名字

入口

main 和 module是入口。
main 字段 是给 node 使用的,node 引用的话会默认去 main 查找,es6或者 webpack 引用 默认查找 module

自定义构建选项

buildOptions
name:全局模块名
formats:当前包可以打包的类型,支持哪些,比如 es6,node,全局

4.build

build.js

  1. // 打包 packages 目录下的所有的包
  2. const fs = require('fs');
  3. const execa = require('execa'); // 开启子进程进行打包
  4. const targets = fs.readdirSync('packages').filter( f => {
  5. // 过滤文件 只保留文件夹
  6. if(!fs.statSync(`packages/${f}`).isDirectory()){
  7. return false;
  8. }
  9. return true;
  10. })
  11. console.log(targets); // [ 'reactivity', 'shared' ]
  12. // 对目标文件夹进行依次打包,并行打包,每个打包有自己的构建方法
  13. async function build(target){ // 通过环境变量将要打包的目标文件信息传递给 rollup
  14. console.log('target',target);
  15. await execa('rollup', ['-c', '--environment', `TARGET:${target}`],
  16. {stdio: 'inherit'}) // 当前子进程的打包信息共享给父进程
  17. }
  18. function runParallel(targets,interatorFn){
  19. const res = targets.map((item) => {
  20. const p = interatorFn(item);
  21. return p
  22. })
  23. console.log('res',res);
  24. return Promise.all(res)
  25. }
  26. runParallel(targets, build)

执行 yarn build 命令会打包packages下所的包,开启子进程并行打包
readdirSync 找到 packages 目录下所有的文件夹,然后对目标文件包依次执行构建方法
打包工具是 rollup,通过环境变量将要打包的目标文件信息传递给 rollup

rollup.config.js

  1. // rollup 配置
  2. import path from 'path'
  3. import json from '@rollup/plugin-json';
  4. import nodeResolve from '@rollup/plugin-node-resolve'
  5. import ts from 'rollup-plugin-typescript2'
  6. // 根据环境变量中的 target 属性 获取对应模块中的 package.json
  7. console.log(process.env.TARGET, 'rollup')
  8. // 找到packages 文件夹
  9. const packagesDir = path.resolve(__dirname,'packages');
  10. // packageDir 是要打包的某个包的基准目录
  11. const packageDir = path.resolve(packagesDir,process.env.TARGET) // process.env.TARGET 从环境变量传过来的包名
  12. // 访问某个包下的文件的路径
  13. const resolve = (p) => path.resolve(packageDir,p);
  14. const pkg = require(resolve('package.json'));
  15. const name = path.basename(packageDir); // 取文件名 "module": "dist/reactivity.esm-bundler.js",
  16. // 对打包类型 做一个映射表,根据 package.json 中配置的 formates 来格式化需要打包的内容
  17. const outputConfigs = {
  18. 'esm-bundler': {
  19. file: resolve(`dist/${name}.esm-bundler.js`),
  20. format: `es`
  21. },
  22. 'cjs': {
  23. file: resolve(`dist/${name}.cjs.js`),
  24. format: 'cjs'
  25. },
  26. 'global': {
  27. file: resolve(`dist/${name}.global.js`),
  28. format: 'iife' // 立即执行函数
  29. }
  30. }
  31. const options = pkg.buildOptions;
  32. function createConfig(format, output) {
  33. output.name = options.name;
  34. output.sourcemap = true; // 生成sourcemap
  35. // 生成 rollup 配置
  36. return {
  37. input: resolve('src/index.js'),
  38. output,
  39. plugin:[
  40. json(),
  41. ts({ // ts 插件
  42. tsconfig: path.resolve(__dirname, 'tsconfig.json')
  43. }),
  44. nodeResolve() // 解析第三方模块
  45. ]
  46. }
  47. }
  48. // 打包定义的类型
  49. export default options.formats.map( format => createConfig(format, outputConfigs[format]));

通过 process.env.TARGE 可以获取到 要打包的目标文件。
通过 path.resolve(‘package.json’) 就可以获取到 目标文件下的 package.json 文件,就能拿到 配置信息,buildOptions name, formates 等。
首先对打包类型做一个映射表
然后根据 buildOptions 里的 formates 属性 过滤出 要打包的类型。
生成 rollup 配置。
最后导出打包信息。

5.dev

执行 yarn dev 的时候会打包单个包,

  1. // 只针对某个具体的包进行打包
  2. const fs = require('fs');
  3. const execa = require('execa'); // 开启子进程进行打包
  4. const target = 'reactivity'
  5. // 对目标文件夹进行依次打包,并行打包,每个打包有自己的构建方法
  6. async function build(target){ // 通过环境变量将要打包的目标文件信息传递给 rollup
  7. console.log('target',target);
  8. await execa('rollup', ['-wc', '--environment', `TARGET:${target}`],
  9. {stdio: 'inherit'}) // 当前子进程的打包信息共享给父进程
  10. }
  11. build(target)

yarn install 产生软链接