UNPKG

complugin

Version:

Unified plugin system for bundle tools.(e.g. rollback, vite, webpack, esbuild)

420 lines (291 loc) 10.9 kB
[npm]: https://img.shields.io/npm/v/complugin [npm-url]: https://www.npmjs.com/package/complugin [size]: https://packagephobia.now.sh/badge?p=complugin [size-url]: https://packagephobia.now.sh/result?p=complugin # complugin [![npm][npm]][npm-url] [![size][size]][size-url] 适用于各种捆绑工具的统一插件系统。(e.g. [rollback](https://rollupjs.org/), [vite](https://vitejs.dev/), [webpack](https://webpack.js.org/), [esbuild](https://esbuild.github.io/)). <p><a href="README.md">English</a> | 中文</p> 目前支持: - [Rollup](https://rollupjs.org/) - [Vite](https://vitejs.dev/) - [Webpack](https://webpack.js.org/) - [esbuild](https://esbuild.github.io/) ## 注意 1. 在`Webpack`中,请不要使用`thread-loader`。 2. 在`esbuild`中, 请使用`complugin.proxyEsbuild(esbuild).build({/* options */})`代替`esbuild.build({/* options */})`。 ## 使用 ```ts import { createComplugin } from 'complugin' interface Options {} export default createComplugin<Options>({ name: 'my-first-complugin', // 插件还可以指定强制属性来调整其应用程序顺序。enforce的值可以是"pre"或"post"。 enforce: 'pre', factory(options, meta) { // 根据不同的捆绑器做具体的事情。 switch (meta.framework) { case 'rollup': // ... break case 'vite': // ... break case 'esbuild': // ... break case 'webpack': // ... break default: // Other bundlers } return { buildStart() { // ... }, resolveId(source, importer) { // ... }, load(id) { // ... }, transformInclude(id) { // ... return false }, transform(code, id) { // ... }, buildEnd() { // ... }, generateBundle(bundle, rawBundle) { // ... } } } }) ``` ### 插件安装 ##### Vite ```ts // vite.config.ts import MyComplugin from './my-complugin' export default { plugins: [ MyComplugin.vite({ /* options */ }), // Or MyComplugin({ /* options */ }).vite ] } ``` ##### Rollup ```ts // rollup.config.js import MyComplugin from './my-complugin' export default { plugins: [ MyComplugin.rollup({ /* options */ }), // Or MyComplugin({ /* options */ }).rollup ] } ``` ##### Webpack ```ts // webpack.config.js const MyComplugin = require('./my-complugin').default module.exports = { plugins: [ MyComplugin.webpack({ /* options */ }), // Or MyComplugin({ /* options */ }).webpack ] } ``` ##### esbuild ```ts // esbuild.config.js import _esbuild from 'esbuild' import { proxyEsbuild } from 'complugin' import MyComplugin from './my-complugin' // Cannot be omitted const esbuild = proxyEsbuild(_esbuild) esbuild.build({ plugins: [ MyComplugin.esbuild({ /* options */ }), // Or MyComplugin({ /* options */ }).esbuild ] }) ``` --- ## Hooks > `complugim`将优秀的`Rollup插件API`作为参考,并为各种捆绑器提供统一的`hook-API`。 ### `buildStart` #### Type: `(this: CompluginMinifyContext) => void` #### Kind: `async` #### Next Hook: `resolveId` 当捆绑器开始构建时调用。 --- ### `resolveId` #### Type: `(source: string, importer?: string) => string | { id: string, external?: boolean } | { name?: string, source: string | Buffer } | null` #### Kind: `async` #### Next Hook: `load` (如果尚未加载已解析的 id) 定义自定义解析器。解析器可用于定位第三方依赖关系。 返回`null`将遵循其他`resolveId`函数,并最终遵循默认的解析行为。 如果返回了一个对象并设置了字符串属性`"id"`,则可以将导入解析为不同的 id,并从包中排除。这允许您将依赖项替换为外部依赖项,而无需用户通过外部选项手动将其标记为`"外部"`。 如果返回了一个对象并设置了属性`"source"`,则将`"source"`的值作为资产内容,并发出一个资产文件。 --- ### `load` #### Type: `(this: CompluginContext, id: string) => string | { code: string, map?: object } | null` #### Kind: `async` #### Next Hook: `transformInclude` (如果没有使用缓存,或者没有具有相同代码的缓存副本) 定义自定义加载程序。返回`null`将遵循其他`load`函数(最终是从文件系统加载的默认行为)。这个钩子可以选择性地返回`{code,map}`对象。 --- ### `transformInclude` #### Type: `(id: string) => boolean` #### Next Hook: `transform` (如果返回`true`) 是否启用转换。如果未设置此钩子,则启用所有转换。 --- ### `transform` #### Type: `(this: CompluginContext, code: string, id: string) => string | { code: string, map?: object } | null` 可用于转换单个模块。这个钩子可以选择性地返回`{code,map}`对象。如果转换不移动代码,则可以通过将映射设置为`null`来保留现有的`sourcemaps`。否则,您可能需要生成源映射。 --- ### `buildEnd` #### Type: `(this: CompluginMinifyContext) => void` #### Kind: `async` #### Next Hook: `generateBundle` 绑定工具完成绑定时调用。 --- ### `generateBundle` #### Type: `(bundle: { [fileName: string]: OutputFile }, rawBundle: unknown) => void` 当绑定工具生成 bundle 对象时调用。 通过从这个钩子中的 bundle 对象中删除文件,可以防止发出文件。 --- ## Hooks Supported | Hook | Rollup | Vite | Webpack4 | Webpack5 | esbuild | | ----------------------------------------------------------------------------- | :----: | :--: | :------: | :------: | :-----: | | [`buildStart`](https://rollupjs.org/guide/en/#buildstart) | | | | | | | [`resolveId`](https://rollupjs.org/guide/en/#resolveid) | | | | | | | [`load`](https://rollupjs.org/guide/en/#load) | | | | | | | `transformInclude`<sup>1</sup> | | | | | | | [`transform`](https://rollupjs.org/guide/en/#transformers)<sup>2</sup> | | | | | | | [`buildEnd`](https://rollupjs.org/guide/en/#buildend) | | | | | | | [`generateBundle`](https://rollupjs.org/guide/en/#generatebundle)<sup>3</sup> | | | | | | 1. `Webpack`的 id 过滤器在加载程序逻辑之外;为了在`webpack`上获得更好的性能,需要额外的钩子。在`rollup`和`vite`中,这个钩子被多填充以匹配行为。 2. 尽管`esbuild`可以处理 JavaScript CSS 以及许多其他文件格式,但只能在“load”和“transform”结果中返回 JavaScript。 3. 为了与各种捆绑工具兼容,该挂钩在设计时与`rollup`的`generateBundle`挂钩不兼容。 --- ## `CompluginMinifyContext` ### `emitFile` #### Type: `(asset: { name?: string, fileName?: string, source: string | Buffer }) => void` 发出包含在生成输出中的新资源文件。 --- ### `error` #### Type: `(message: string) => never | void` 在结构上等同于`this.warn`. 警告,但当绑定器为“rollup”或“vite”时,它也会中止绑定过程。 --- ### `warn` #### Type: `(message: string) => void` 使用此方法将对生成的警告进行排队。 --- ### `resolve` #### Type: `(source: string, importer?: string) => Promise<{ id: string; external?: boolean } | undefined>` 使用捆绑器使用的相同插件将导入解析为模块 ID(即文件名),并确定导入是否应该是外部的。如果返回 null,则绑定器或任何插件都无法解析导入,但用户未明确将其标记为外部。 在`webpack`中,某些模块 id 无法正确识别为外部。 --- ## `CompluginContext` ### `emitAsset` #### Type: `(asset: { name?: string, fileName?: string, source: string | Buffer }): string` 发出一个包含在生成输出中的新资源文件,并返回一个占位符表达式,该表达式可在不同位置用于引用发出的文件。 例如: ```ts const hooks = { // ...others hook, load(id) { const placeholder = this.emitAsset({ name: 'hello world.txt', source: 'hello world!' }) return ` import { readFile } from 'fs/promises' const fileName = ${placeholder} readFile(fileName).then((content) => { console.log(content.toString()) // hello world! }) ` } } ``` --- ### `addWatchFile` #### Type: `(fileName: string) => void` 添加要在监视模式下监视的其他文件,以便对这些文件的更改将触发重建。 ## API ### `createComplugin` #### Type: `<UserOptions = {}>(args: CreateCompluginArgs<UserOptions>) => CompluginInstance<UserOptions>` create a complugin. --- ### `utils` plugin utils. --- ### `proxyEsbuild` #### Type: `(esbuild: typeof import('esbuild')) => typeof import('esbuild')` At present, the generated esbuild-plugin needs to run in the esbuild environment proxied by `proxyEsbuild()`. --- ### `registerCompluginGenerator` #### Type: `(framework: string, generator: <UserOptions = {}>(args: CreateCompluginArgs<UserOptions>, userOptions?: UserOptions) => any) => void` Register custom plugin generator. e.g ```ts import { registerCompluginGenerator, commonInputFS } from 'complugin' import MyComplugin from './my-complugin' // Register registerCompluginGenerator('custom', function ({ name, enforce, factory }, options) { const meta = { // required framework: 'custom', version: '1.0.0', inputFS: { ...commonInputFS } // ...others } const { buildStart, resolveId, load, transformInclude = () => true, transform, buildEnd, generateBundle } = factory(options, meta) return // ... }) // Usage const createdCustomPlugin = MyComplugin.custom({ /* options */ }) const createdCustomPluginOr = MyComplugin({ /* options */ }).custom ``` --- ## Give a ⭐️ if this project helped you! ## License [MIT](./LICENSE) License © 2022 xxXyh1908