esbuild.base.ts (132 lines of code) (raw):

const esbuild = require('esbuild'); const fs = require('fs'); const ts = require('typescript'); const { lessLoader } = require('esbuild-plugin-less'); const { getCompilerOptions, } = require('./scripts/esbuild/getCompilerOptions.js'); const { resolveTSConfig } = require('./scripts/esbuild/resolveTSConfig.js'); const builder = async (type, entryPoints, outbase, outdir) => { esbuild .build({ entryPoints, // 你的入口文件 outdir, bundle: false, // 是否打包 minify: false, // 是否压缩 outbase, format: type, platform: 'node', // 目标平台: 'node' 或 'browser' target: 'es2015', metafile: true, plugins: [ lessLoader(), { name: 'dts-plugin', async setup(build) { const { config } = resolveTSConfig({}); const willBundleDeclarations = false; const compilerOptions = getCompilerOptions({ tsconfig: config, pluginOptions: { tsconfig: { outdir } }, esbuildOptions: build.initialOptions, willBundleDeclarations, }); const compilerHost = compilerOptions.incremental ? ts.createIncrementalCompilerHost(compilerOptions) : ts.createCompilerHost(compilerOptions); const inputFiles = []; build.onLoad({ filter: /(\.tsx|\.ts)$/ }, async (args) => { inputFiles.push(args.path); compilerHost.getSourceFile( args.path, compilerOptions.target ?? ts.ScriptTarget.Latest, true, ); }); build.onEnd(() => { let compilerProgram; if (compilerOptions.incremental) { compilerProgram = ts.createIncrementalProgram({ options: compilerOptions, host: compilerHost, rootNames: inputFiles, }); } else { compilerProgram = ts.createProgram( inputFiles, compilerOptions, compilerHost, ); } compilerProgram.emit(); }); }, }, { name: 'transform-import-less-to-css', async setup(build) { const distFile = []; const esFile = []; build.onLoad({ filter: /(\.tsx)$/ }, async (args) => { const distPath = args.path ?.replace('src', 'dist') .replace('tsx', 'js'); const esPath = args.path ?.replace('src', 'es') .replace('tsx', 'js'); distFile.push(distPath); esFile.push(esPath); }); build.onEnd(async (buildResult) => { if (buildResult.errors?.length) { return null; } const { outputs } = buildResult?.metafile || {}; const assets = Object.keys(outputs); assets.forEach((asset) => { if (asset.endsWith('.js')) { const assetPath = `${process.cwd()}/${asset}`; fs.readFile(assetPath, 'utf8', (readErr, data) => { if (readErr) console.error(`构建失败: ${readErr}`); if (!data) return; if ( data.match( /(import_react\.default\.memo|import_react\.default\.forwardRef|React\.forwardRef|React\.memo|\.less)/gm, ) ) { /** * 1、将js中less改css引入 * 2、处理esbuild构建在forwardRef、memo场景不会注入PURE * https://github.com/evanw/esbuild/issues/3492 */ const result = data .replace('.less', '.css') .replace( /(import_react\.default\.memo|import_react\.default\.forwardRef|React\.forwardRef|React\.memo)/gm, `/* @__PURE__ */ $1`, ); fs.writeFile(assetPath, result, (writeErr) => { if (writeErr) console.error(`构建失败: ${writeErr}`); }); } }); if ( asset.endsWith('.types.js') && assetPath.includes('/es/') ) { fs.writeFile(assetPath, 'export {};', (writeErr) => { if (writeErr) console.error(`构建失败: ${writeErr}`); }); } } }); }); }, }, ], }) .catch(() => process.exit(1)); }; const esBuilder = (entryPoints) => { const outbase = 'src'; const esmOutdir = 'es'; const cjsOutdir = 'dist'; builder('esm', entryPoints, outbase, esmOutdir); builder('cjs', entryPoints, outbase, cjsOutdir); }; module.exports = esBuilder;