你的Typescript项目也是使用 rollup+api-extractor 打包的吗?
最终打包效果
这里以
web-loading
插件为例。最初使用Webpack
打包,因为其灵活性和多样化的生态,支持多种加载器和插件。但是,后来发现我的项目并没有涉及到复杂的加载器和插件功能,Webpack
更适用于框架项目。因此,我转向了更为轻便的Rollup
,并使用api-extractor
来合并TS类型定义,使得打包后的插件文件更加紧凑、大小更小。
安装
npm i typescript rollup rollup-plugin-terser @microsoft/api-extractor -D
package.json重要配置
{
"main": "./dist/web-loading.js", // 指定引入入口
"typings": "./dist/web-loading.d.ts", // 指定TypeScript类型入口,提供给Typescript编译器使用
"jsdelivr": "./dist/web-loading.js", // 指定了通过 jsdelivr CDN 加载的入口文件路径
"unpkg": "./dist/web-loading.js", // 指定了通过 unpkg CDN 加载的入口文件路径
"module": "./dist/web-loading.esm-bundler.js", // 指定ES Module引入入口
"scripts": {
// 首先tsc 打包,rollup抽离,api-extractor run 合并ts类型
"build": "tsc && rollup -c rollup.config.js && api-extractor run",
},
}
可以在打包完成之后根据自己的路径填充。
tsc配置文件
tsconfig.json
{
"compilerOptions": {
"target": "ES5",
"module": "ESNext",
"declaration": true,
"outDir": "lib"
},
"include": [
"./src/**/*"
]
}
这里根据自己业务指定,这里是最终将项目打包成ES模块项目,并最终输出到根目录的lib路径中。
tsc
之后的效果
rollup配置文件
rollup.config.js
import { defineConfig } from 'rollup'
import { join } from 'path'
import { terser as rollupTerser } from 'rollup-plugin-terser'
import rollupJSON from '@rollup/plugin-json'
import rollupCommonJS from '@rollup/plugin-commonjs'
import rollupReplace from '@rollup/plugin-replace'
import rollupNodeResolve from '@rollup/plugin-node-resolve'
/**
* @typedef {'umd' | 'cjs' | 'esm-bundler'} OutputFormat
*/
/**
* @param {OutputFormat} format
* @param {boolean} minify
* @returns {string}
*/
function replaceProcessNodeEnv(format, minify) {
switch (format) {
case 'umd':
case 'cjs':
return minify ? '"production"' : '"development"'
case 'esm-bundler':
return 'process.env.NODE_ENV'
default:
throw new TypeError(`Unsupport format: ${format}`)
}
}
/**
* @param {OutputFormat} format
* @param {boolean} minify
* @returns {string}
*/
function replaceDev(format, minify) {
switch (format) {
case 'umd':
case 'cjs':
return minify ? 'false' : 'true'
case 'esm-bundler':
return 'process.env.NODE_ENV !== "production"'
default:
throw new TypeError(`Unsupport format: ${format}`)
}
}
/**
* @param {OutputFormat} format
* @param {boolean} minify
* @returns {import('rollup').RollupOptions}
*/
function createOption(format, minify) {
// 需要指定输出文件前缀
const name = `web-loading${format === 'umd' ? '' : `.${format}`}${minify ? '.min' : ''}.js`
return {
// 入口
input: join(__dirname, 'lib/index.js'),
plugins: [
rollupNodeResolve({
mainFields: ['browser', 'module', 'main']
}),
rollupJSON(),
rollupReplace({
preventAssignment: true,
'process.env.NODE_ENV': replaceProcessNodeEnv(format, minify),
__DEV__: replaceDev(format, minify),
__VERSION__: JSON.stringify(require('./package.json').version)
}),
rollupCommonJS({
transformMixedEsModules: true,
extensions: ['.js', 'jsx', '.ts', '.tsx']
}),
{
name: 'typescript-class-pure',
transform(code) {
return code.replace(//** @class */ (function/g, '/*#__PURE__*/ (function')
}
},
...(minify
? [
rollupTerser({
output: {
comments: false
},
module: format === 'esm-bundler'
})
]
: [])
],
output: {
// 最终输出文件路径
file: join(__dirname, 'dist', name),
format: format === 'esm-bundler' ? 'esm' : format,
name: 'rustOption',
exports: 'named'
}
}
}
export default defineConfig([
createOption('umd', false),
createOption('umd', true),
createOption('cjs', false),
createOption('cjs', true),
createOption('esm-bundler', false)
])
这里可以把它当作固定写法,也可以自定义,但
createOption
函数中输出可以自定义文件前缀。
rollup -c rollup.config.js
之后的效果
此时已经将
lib
中的js
文件抽离,并打包了输出dist
路径中。
api-extractor配置文件
api-extractor.json
{
"$schema": "https://developer.microsoft.com/json-schemas/api-extractor/v7/api-extractor.schema.json",
"mainEntryPointFilePath": "<projectFolder>/lib/index.d.ts",
"bundledPackages": [],
"compiler": {
"tsconfigFilePath": "<projectFolder>/tsconfig.json"
},
"apiReport": {
"enabled": false
},
"docModel": {
"enabled": true
},
"dtsRollup": {
"enabled": true,
// 合并类型后的文件名
"untrimmedFilePath": "<projectFolder>/dist/web-loading.d.ts"
},
"tsdocMetadata": {
"enabled": true,
"tsdocMetadataFilePath": "<projectFolder>/dist/tsdoc-metadata.json"
},
"messages": {
"compilerMessageReporting": {
"default": {
"logLevel": "warning"
}
},
"extractorMessageReporting": {
"default": {
"logLevel": "warning"
},
"ae-forgotten-export": {
"logLevel": "none"
}
},
"tsdocMessageReporting": {
"default": {
"logLevel": "warning"
}
}
}
}
注意
untrimmedFilePath
最后输出的类型文件名。
api-extractor run
之后的效果
可以看到项目中新增了合并后的类型文件,最后根据package.json配置入口即可。
npm上传配置
为了上传npm插件包时减小文件体积,可以新增一个名为.npmignore
的配置文件,并在其中列出不需要被上传到npm注册表中的文件或目录。这样,在运行npm publish
后,只会将定义在package.json
中的files
字段以及符合.npmignore
设置的文件列表一并打包发布,自己的源码就不会被上传到npm仓库,从而使npm插件包的文件大小更小。
src
temp
lib
.eslint*
docs
api-extractor.json
rollup.config*
tsconfig*
package-lock.json
转载自:https://juejin.cn/post/7244192848063987773