Vite 学习三 - rollup & esbuild 基础学习

本小节介绍下 rollupesbuild 的基础用法,我们都知道 vite 本身使用的 rollup 打包,vite 的插件也和 rollup 的插件机制相吻合; esbuild 是用于在开发环境中对文件进行处理,也有自己的声明周期钩子函数,由于对文件的分割和 css 支持还不太友好,暂未应用到打包环节。

rollup

rollup 是成熟的构建工具, 开源类库优先选择,以 esm 标准为目标的构建工具,package.json 中提供了 module 字段,引用时以这个字段为主,不是 main,默认不支持 commonjs,需要使用插件 resolvenode 实现转换,webpack 适合企业级项目,写好的 loaderplugins,打包优化

  • tree shaking

rollup 令人津津乐道的就是 treeshaking 功能,把没有使用的代码剔除,减小打包体积

如下一段代码

function test() {

    var name = 'test';

    console.log(123);

}

const name = '测试测试';

function fn() {

    console.log(name);

}



fn();

打包后没有 test 函数的代码

'use strict';



const name = '测试测试';

function fn() {

    console.log(name);

}



fn();

实现原理还是依赖于 ast 解析,也是为什么需要使用 esm 标准,解析的时候,会把代码统一到一个文件的最上层,importexport 的字段都会打上标记,在哪里定义,在哪里使用的。自然未使用的也不会引入。

常用命令

  • npm i -g rollup 全局安装
  • rollup -i index.js 打包 index.js 文件,在控制台查看内容
  • rollup -i index.js --file dist.js 打包文件输出到 dist.js 中
  • rollup -i index.js --file dist.js --format umd 以 umd 模式打包,

还有 iife cjs umd 模式

  • rollup -i index.js a.js --dir dist 打包到dist 目录下,会自动生成index.js
  • rollup -i index.js --file dist.js --format umd --name Index (--watch) 可以全局 global 命名

  • rollup -h (--help) 查看命令

rollup.config.js

执行命令 rollup -c rollup.config.js --environment TEST:123

// 命令行定义环境变量,在脚本中可以直接获取

console.log(process.env.TEST)



export default {

  input: 'index.js',

  output: {

    file: 'dist.js',

    // 打包模式可以条件判断

    format: isLocal ? 'es' : 'umd',

    name: 'Index'

  }

}

如果我们全局安装了 rollup,命令行执行操作会使用全局 rollup,如果想使用项目内的,执行 node\_modules 下的:

./node_modules/.bin/rollup -c rollup.config.js --plugin json

配置文件

rollup 不光可以打包一个文件,也可以打包多种,我们看下 vue3 打包出的种类如下,配置文件中导出数组形式即可

默认 根目录 

// 模块引入可以不加后缀名或者引入目录下的 index.js 可以简写

improt resolve from '@rollup/plugin-node-resolve'

// commonjs 转为 esm

import commonjs from '@rollup/commonjs'

// 压缩

import {terser} from 'rollup-plugin-terser'

export default [

  {

    input:'index.js',

    // 不想打包进的,我们使用 cdn 引入

    external: ['react', {

      // 对象需要全局名字

      ‘react’: 'React'

    }],

    output: {

      file: 'dist/index.umd.js',

      format: 'umd',

      // 也有 plugin,编译完才用,压缩

      plugins: [

        terser()

      ],

      // 和 terser 冲突,因为这是属于注释的内容

      banner: '/\*\* hellp this is banner'

    },

    // 默认放第一个,先执行

    plugins: [

      resolve(), commonjs(), json()

    ]

  },

  {

    input:'index.js',

    output: {

      file: 'dist/index.es.js',

      format: 'es'

    }

  }

]

命令行命令默认全局, package.json 中默认本地 node\_modules 下的

rollup 插件

执行机制

input -> rollup main code -> plugin1 -> plugin2 ... -> emit file 输出到文件-> finish

我们编写插件就是对象要操作的类型的文件,根据不同 hook 在不同节点执行不同方法,完成我们想要的目的

配置对什么文件执行插件操作,什么文件不执行操作关键字:includeexclude

  • @rollup/plugin-alias 设置别名
import a from '../a' // ..写法繁琐想简写如下

import a from 'a'



// 插件配置

plugins: [

  alias({

    entries: {

      a: "../a",// 页面的 ../a 用 a 替换

    },

  }),

],

源码

// 最后是导出一个插件函数

...

export default function alias(options: RollupAliasOptions = {})

...



// 函数返回

return {

    name: 'alias',// 插件名,报错查看

    // inputOptions 对应 rollup.config.js 写的配置 导出的值

    // 构建之前处理

    async buildStart(inputOptions) {

      await Promise.all(

        [...(Array.isArray(options.entries) ? options.entries : []), options].map(

          ({ customResolver }) =>

            customResolver &&

            typeof customResolver === 'object' &&

            typeof

    

    // 路径映射  a          ../a   

    resolveId(importee, importer) {

      // 返回真正的 路径

    }

其他相对重要的钩子函数如:

  • transform
  • 类型: Function
  • 形式: ( source, id ) => (code|{ code, map, dependencies }|Promise)

可以被用来改变每个模块代码。在 --watch 模式中, 会监听 dependencies 数组中所有文件或者目录的变化。

例如我们使用 replace 插件,对文件内容进行替换

具体大家可以去官网学习

esbuild

因为 vite 内部文件编译使用了 esbuild,他是 go 语言写的,完全命令行使用,能够解析 js ,但是不能运行 js。代码中也是间接通过 node 执行命令行工具操作。我们需要了解 esbuild 的插件执行机制,我们在编写 vite 插件的时候,如果写自己插件有需要的话,也要同时兼容 rollupesbuild

使用

npx esbuild index.js

npx esbuild index.js --ourfile=dist.js 输出

想打包的话(所有代码打包到一起)加上 --bundle,内部有 treeshaking

--target=esnext 指定编译目标,注意 esbuild 对 es5 编译不完整,const 依旧会 va

--platform=node, browser node 环境或者浏览器环境

--format=esm cjs

--watch

--define:TEST=12 环境变量

如果项目中使用了图片,需要使用 loade

import a from './logo.png'

--loader:.png=dataurl // 转成了 base64

esbuild 插件

esbuild 中,插件被设计为一个函数,该函数需要返回一个对象(Object),对象中包含 namesetup 等 2 个属性

build 对象上会暴露整个构建过程中非常重要的 2 个函数:onResolveonLoad,它们都需要传入 Options(选项)和 CallBack(回调)等 2 个参数。

// build.js



let exampleOnLoadPlugin = {

  name: "example", // 名字为了报错警告提示

  setup(build) {

    let fs = require("fs");



    // 输入的 options

    console.log(build.initialOptions);

    // 我们可以在操作中修改配置  build.initialOptions.outdir = 'lib'

    /\*\*

      build.onStart({}, () => {

          // 不能再 onstart 中修改配置

      })

    \*/

    

    // 处理哪类文件

    build.onResolve(

      {

        filter: /\.txt$/,

      },

      async (args) => ({

        path: args.path,

        namespace: "txt", // 区分文件加载,标识

      })

    );



    build.onLoad(

      {

        // 在 go 里执行 正则

        filter: /\.\*$/, //什么类型文件执行



        namespace: "txt",

      },

      async (args) => {

        // 模块的文件路径

        let text = await fs.promises.readFile(args.path, "utf-8");

        return {

          // 文件内容预处理

          contents: `export default ${JSON.stringify([

            ...text.split(/\s+/),

            "----------",

          ])}`,

          // loader: "json",

        };

      }

    );

  },

};



require("esbuild")

  .build({ // 命令行参数

    entryPoints: ["index.js"],

    bundle: true,

    outdir: "dist",

    loader: {

      ".png": "dataurl",

    },

    plugins: [exampleOnLoadPlugin],

  })

  .catch(() => process.exit(1));

onResolve 的回调函数

onResolve 函数的回调函数会在 esbuild 构建每个模块的导入路径(可匹配的)时执行。

onResolve 函数的回调函数需要返回一个对象,其中会包含 pathnamespaceexternal 等属性。

通常,该回调函数会用于自定义 esbuild 处理 path 的方式,例如:

重写原本的路径,例如重定向到其他路径

将该路径所对应的模块标记为 external,即不会对改文件进行构建操作(原样输出)

onLoad 的回调函数

onLoad 函数的回调函数会在 esbuild 解析模块之前调用,主要是用于处理并返回模块的内容,并告知 esbuild 要如何解析它们。并且,需要注意的是 onLoad 的回调函数不会处理被标记为 external 的模块。

onLoad 函数的回调函数需要返回一个对象,该对象总共有 9 个属性。这里我们来认识一下较为常见 2 个属性:

contents 处理过的模块内容

loader 告知 esbuild 要如何解释该内容(默认为 js)。例如,返回的模块内容是 CSS,则声明 loadercss

本节对 rollupesbuild 中的常见使用方式做了介绍,包括常用命令和插件的使用,下一节会介绍下 vite 插件的学习使用,如果有问题欢迎留言,谢谢阅读!

原文地址:https://cloud.tencent.com/developer/article/1942747

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


学习编程是顺着互联网的发展潮流,是一件好事。新手如何学习编程?其实不难,不过在学习编程之前你得先了解你的目的是什么?这个很重要,因为目的决定你的发展方向、决定你的发展速度。
IT行业是什么工作做什么?IT行业的工作有:产品策划类、页面设计类、前端与移动、开发与测试、营销推广类、数据运营类、运营维护类、游戏相关类等,根据不同的分类下面有细分了不同的岗位。
女生学Java好就业吗?女生适合学Java编程吗?目前有不少女生学习Java开发,但要结合自身的情况,先了解自己适不适合去学习Java,不要盲目的选择不适合自己的Java培训班进行学习。只要肯下功夫钻研,多看、多想、多练
Can’t connect to local MySQL server through socket \'/var/lib/mysql/mysql.sock问题 1.进入mysql路径
oracle基本命令 一、登录操作 1.管理员登录 # 管理员登录 sqlplus / as sysdba 2.普通用户登录
一、背景 因为项目中需要通北京网络,所以需要连vpn,但是服务器有时候会断掉,所以写个shell脚本每五分钟去判断是否连接,于是就有下面的shell脚本。
BETWEEN 操作符选取介于两个值之间的数据范围内的值。这些值可以是数值、文本或者日期。
假如你已经使用过苹果开发者中心上架app,你肯定知道在苹果开发者中心的web界面,无法直接提交ipa文件,而是需要使用第三方工具,将ipa文件上传到构建版本,开...
下面的 SQL 语句指定了两个别名,一个是 name 列的别名,一个是 country 列的别名。**提示:**如果列名称包含空格,要求使用双引号或方括号:
在使用H5混合开发的app打包后,需要将ipa文件上传到appstore进行发布,就需要去苹果开发者中心进行发布。​
+----+--------------+---------------------------+-------+---------+
数组的声明并不是声明一个个单独的变量,比如 number0、number1、...、number99,而是声明一个数组变量,比如 numbers,然后使用 nu...
第一步:到appuploader官网下载辅助工具和iCloud驱动,使用前面创建的AppID登录。
如需删除表中的列,请使用下面的语法(请注意,某些数据库系统不允许这种在数据库表中删除列的方式):
前不久在制作win11pe,制作了一版,1.26GB,太大了,不满意,想再裁剪下,发现这次dism mount正常,commit或discard巨慢,以前都很快...
赛门铁克各个版本概览:https://knowledge.broadcom.com/external/article?legacyId=tech163829
实测Python 3.6.6用pip 21.3.1,再高就报错了,Python 3.10.7用pip 22.3.1是可以的
Broadcom Corporation (博通公司,股票代号AVGO)是全球领先的有线和无线通信半导体公司。其产品实现向家庭、 办公室和移动环境以及在这些环境...
发现个问题,server2016上安装了c4d这些版本,低版本的正常显示窗格,但红色圈出的高版本c4d打开后不显示窗格,
TAT:https://cloud.tencent.com/document/product/1340