前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Vite 学习(三) - rollup & esbuild 基础学习

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

原创
作者头像
测不准
发布2022-02-13 00:03:04
1.8K0
发布2022-02-13 00:03:04
举报
文章被收录于专栏:与前端沾边与前端沾边

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

rollup

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

  • tree shaking

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

如下一段代码

代码语言:txt
复制
function test() {

    var name = 'test';

    console.log(123);

}

const name = '测试测试';

function fn() {

    console.log(name);

}



fn();

打包后没有 test 函数的代码

代码语言:txt
复制
'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

代码语言:txt
复制
// 命令行定义环境变量,在脚本中可以直接获取

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 打包出的种类如下,配置文件中导出数组形式即可

代码语言:txt
复制
默认 根目录 

// 模块引入可以不加后缀名或者引入目录下的 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 设置别名
代码语言:txt
复制
import a from '../a' // ..写法繁琐想简写如下

import a from 'a'



// 插件配置

plugins: [

  alias({

    entries: {

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

    },

  }),

],

源码

代码语言:txt
复制
// 最后是导出一个插件函数

...

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

代码语言:txt
复制
import a from './logo.png'

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

esbuild 插件

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

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

代码语言:txt
复制
// 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 插件的学习使用,如果有问题欢迎留言,谢谢阅读!

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • rollup
    • 常用命令
    • rollup.config.js
    • 配置文件
    • rollup 插件
    • esbuild
      • 使用
        • esbuild 插件
          • onResolve 的回调函数
          • onLoad 的回调函数
      相关产品与服务
      命令行工具
      腾讯云命令行工具 TCCLI 是管理腾讯云资源的统一工具。使用腾讯云命令行工具,您可以快速调用腾讯云 API 来管理您的腾讯云资源。此外,您还可以基于腾讯云的命令行工具来做自动化和脚本处理,以更多样的方式进行组合和重用。
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档