VUE3源码分析————rollup打包

什么是rollup

Rollup 是一个 JavaScript 模块打包工具,可以将多个小的代码片段编译为完整的库和应用。与传统的 CommonJS 和 AMD 这一类非标准化的解决方案不同,Rollup 使用的是 ES6 版本 Javascript 中的模块标准。新的 ES 模块可以让你自由、无缝地按需使用你最喜爱的库中那些有用的单个函数。这一特性在未来将随处可用,但 Rollup 让你现在就可以,想用就用。

rollup打包和webpack打包的区别

   在vue2中,打包采用的是webpack,而到了vue3中打包就变成了rollup,而且不仅仅vue3采用了rollup来打包,react也从webpack到rollup转变了。那么rollup打包工具是不是要比webpack打包要好呢?其实各自有各自的用途,我们通过对比vue2和vue3的一些用法就可以简单的看出来两者打包工具的一些区别,vue3最大的一个特性就说采用了组合式API,简单来说vue2更多的像一个百宝箱,我们可以开箱即用,而vue3更多的是提供一些基础功能,然后让使用者去选择,灵活使用。

   两者打包工具各自有各自的好处,就像一句话说的"webpack是大而全,rollup是小而美"。首先相对于webpack来说rollup更加轻量级,同时rollup是一个JS模块打包器,更适合于JS库打包,而webpack更适合的是大型项目。

rollup打包准备

一、安装yarn
npm install -g yarn

安装完成之后查看是否安装成功

yarn -v

配置yarn库镜像网站

yarn config set npmRegistryServer https://registry.npm.taobao.org

开始rollup打包

一、初始化
yarn init -y

执行该命令后会生成一个package.json文件

二、package.json文件配置
{
  "private": true,
  "workspaces": [
    "packages/*"
  ],
  "name": "vue3",
  "type": "module",
  "version": "1.0.0",
  "main": "index.js",
  "scripts": {
    "build": "node scripts/build.js"
  },
  "license": "MIT",
}

workspaces相当于指定了我们的工作作用域,即packages下的文件夹,scripts指定了一些脚本我们打包的时候直接运行就可以打包了

npm run build
三、新建并配置打包文件夹

   新建文件夹packages,并在packages文件夹里边新建文件夹reactivity在reactivity文件夹的路径下执行初始化命令

yarn init -y

reactivity文件夹中的package.json文件配置

{
  "name": "@vue/reactivity",
  "version": "1.0.0",
  "main": "index.js",
  "license": "MIT",
  "buildOptions": {
    "name": "VueReactivity",
    "formats": [
      "esm-bundler",
      "cjs",
      "global"
    ]
  }
}

formats指定的是打包的不同的文件
在reactivity文件夹中新建文件夹src,在src文件夹中新建index.ts文件,在index.ts文件中随便写点东西,否则打包的时候会因为文件里边没有内容而报错

四、下载rollup及打包执行文件

在项目文件中执行命令

安装typescript

yarn add typescript -D -W

生成ts配置文件

npx tsc --init

安装rollup打包相关依赖

yarn add rollup rollup-plugin-typescript2 @rollup/plugin-node-resolve @rollup/plugin-json execa -D -W

新建文件夹scripts(该文件夹存放的是执行打包的文件,该文件夹与packages属于同一级)
在scripts文件中新建文件build.js之后打包执行的就是这个文件
build.js文件内容

// 进行打包
// (1)获取 打包 目录
import * as fs from 'fs';
import { execa } from 'execa'
// 获取目录,注意只打包packages下边的文件夹
const dirs = fs.readdirSync('packages').filter(p => {
    // 判断是否是文件,只打包文件夹
    if (!fs.statSync(`packages/${p}`).isDirectory()) {
        return false
    }
    return true
})
// (2)进行打包 并行打包
async function build(target) {
    // execa第一个参数是打包的形式,第二个是一个数组
    // -c 执行rullup配置,环境变量
    await execa('rollup', ['-c', '--environment', `TARGET:${target}`], { stdio: "inherit" })//子进程的输出在父进程里边出现
}

async function runParaller(dirs, itemfn) {
    // 遍历所有包
    let result = []
    for (let item of dirs) {
        result.push(itemfn(item))
    }
    return Promise.all(result)//存放打包的promise,等待这里的打包执行完毕之后,调用成功
}
runParaller(dirs, build)
    .then(() => {
        console.log('成功');
    })
    .catch((err) => {
        console.log('错误', err);
    })

在项目文件中新建rollup.config.js用来写rullup执行时的配置

// 通过rollup进行打包
// (1) 引入相关依赖
import ts from 'rollup-plugin-typescript2' //解析 ts
import json from '@rollup/plugin-json' //解析json
import resolvePlugin from '@rollup/plugin-node-resolve' //解析 第三方插件
import path from 'path' //处理路径
// 获取路径
import { fileURLToPath } from 'url';
import { dirname } from 'path';
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
// 讲require转换为模块
import { createRequire } from 'module';
const require = createRequire(import.meta.url);
// (2)获取文件路径
let packagesDir = path.resolve(__dirname, 'packages')
// 获取需要打包的包
let packageDir = path.resolve(packagesDir, process.env.TARGET)
// 打包获取到每个包的项目配置
let resolve = p => path.resolve(packageDir, p)
const pkg = require(resolve(`package.json`))//获取json配置
const packageOptions = pkg.buildOptions || {}
// 获取文件名字
const name = path.basename(packageDir)
// 创建一个映射表
const outputOpions = {
    "esm-bundler": {
        // 输出文件的名字
        file: resolve(`dist/${name}.esm-bundler.js`),
        // 输出文件的格式
        format: 'es'
    },
    "cjs": {
        // 输出文件的名字
        file: resolve(`dist/${name}.cjs.js`),
        // 输出文件的格式
        format: 'cjs'
    },
    "global": {
        // 输出文件的名字
        file: resolve(`dist/${name}.global.js`),
        // 输出文件的格式
        format: 'iife'
    },
}
// 获取需要打包的文件的自定义配置
const options = pkg.buildOptions
function createConfig(format, output) {
    // 进行打包
    output.name = options.name//指定一个名字
    // 用于调整代码
    output.sourcemap = true
    // 生成rollup配置
    return {
        // resolve表示当前包
        input: resolve('src/index.ts'),//导入
        // 输出
        output,
        // 
        plugins: [
            json(),
            ts({//解析ts语法
                tsconfig: path.resolve(__dirname, 'tsconfig.json')
            }),
            resolvePlugin()//解析第三方插件
        ]
    }
}
// rullup需要导出一个配置
export default options.formats.map(format => createConfig(format, outputOpions[format]))
五、文件大致分布image.pngimage.png

可能报错及解决方案

1、Warning: To load an ES module, set “type”: “module” in the package.json or use the .mjs extension

在最外层的package.json文件指定一下

"type": "module",
2、(plugin rpt2) RollupError: Incompatible tsconfig option. Module resolves to ‘CommonJS’. This is incompatible with Rollup, please use ‘module: “ES2015”’, ‘module: “ES2020”’, or ‘module: “ESNext”’

将tsconfig.json中的target和module的值改为ESNext,并把strict改为false

3、__dirname不可使用
// 获取路径
import { fileURLToPath } from 'url';
import { dirname } from 'path';
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
4、require is not found
// 将require转换为模块
import { createRequire } from 'module';
const require = createRequire(import.meta.url);

当我们看到控制台输出成功之后,并且reactivity文件夹中多了个dist文件夹就代表打包成功了

总结

   以上就是我在学习过程中遇到的rollup打包的一些配置及我所遇到的一些问题,程度有限,有那些不足的或者有些问题我没遇到的,也希望各位大佬能够指出,彼此学习,互相进步。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值