feat: add rollup-tools

This commit is contained in:
xion 2024-11-22 01:40:49 +08:00
parent b4cca6e345
commit 5ed479e74f
15 changed files with 500 additions and 0 deletions

1
.npmrc
View File

@ -1 +1,2 @@
@kevisual:registry=https://npm.xiongxiao.me
//registry.npmjs.org/:_authToken=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

View File

@ -0,0 +1,4 @@
#!/usr/bin/env node
import { runParser } from '../dist/run.mjs';
runParser(process.argv);

View File

@ -0,0 +1,46 @@
{
"name": "@kevisual/rollup-tools",
"version": "0.0.1",
"description": "",
"scripts": {
"build": "rollup -c rollup.config.mjs",
"clean": "rimra dist"
},
"private": false,
"bin": {
"ev": "bin/ev.js"
},
"files": [
"dist",
"bin"
],
"keywords": [],
"author": "abearxiong <xiongxiao@xiongxiao.me>",
"license": "MIT",
"type": "module",
"dependencies": {
"@rollup/plugin-alias": "^5.1.1",
"@rollup/plugin-commonjs": "^28.0.1",
"@rollup/plugin-json": "^6.1.0",
"@rollup/plugin-node-resolve": "^15.3.0",
"@rollup/plugin-replace": "^6.0.1",
"@rollup/plugin-typescript": "^12.1.1",
"@types/node": "^22.9.0",
"chalk": "^5.3.0",
"commander": "^12.1.0",
"glob": "^11.0.0",
"rollup": "^4.26.0",
"rollup-plugin-copy": "^3.5.0",
"rollup-plugin-dts": "^6.1.1",
"rollup-plugin-esbuild": "^6.1.1",
"rollup-plugin-inject": "^3.0.2",
"tslib": "^2.8.1",
"typescript": "^5.6.2"
},
"exports": {
".": "./dist/app.mjs"
},
"publishConfig": {
"access": "public"
}
}

View File

@ -0,0 +1 @@
# 自用封装

View File

@ -0,0 +1,101 @@
import typescript from '@rollup/plugin-typescript';
import resolve from '@rollup/plugin-node-resolve';
import commonjs from '@rollup/plugin-commonjs';
import { dts } from 'rollup-plugin-dts';
import json from '@rollup/plugin-json';
import path from 'path';
import alias from '@rollup/plugin-alias';
import esbuild from 'rollup-plugin-esbuild';
import replace from '@rollup/plugin-replace';
import * as glob from 'glob';
import inject from 'rollup-plugin-inject';
/**
* @type {import('rollup').RollupOptions}
*/
const config = {
input: './src/app.ts',
output: {
dir: './dist',
entryFileNames: 'app.mjs',
chunkFileNames: '[name]-[hash].mjs',
format: 'esm',
},
plugins: [
resolve(),
commonjs(),
esbuild({
target: 'node22', // 目标为 Node.js 14
minify: false, // 启用代码压缩
tsconfig: 'tsconfig.json',
}),
json(),
],
external: [],
};
const dtsConfig = {
input: './src/app.ts',
output: {
file: './dist/app.d.ts',
format: 'esm',
},
plugins: [dts()],
};
const program = {
input: './src/run.ts',
output: {
dir: './dist',
entryFileNames: 'run.mjs',
chunkFileNames: '[name]-[hash].mjs',
format: 'esm',
banner: `
import { fileURLToPath as fileURLToPath2, pathToFileURL as pathToFileURL2} from 'url';
const __filename = fileURLToPath2(import.meta.url);
const __dirname = dirname(__filename);`,
},
plugins: [
resolve(),
commonjs(),
esbuild({
target: 'node22', // 目标为 Node.js 14
minify: false, // 启用代码压缩
tsconfig: 'tsconfig.json',
}),
json(),
],
external: ['rollup'],
};
const configs = glob.sync('./src/**/*config.ts').map((input) => {
const name = path.basename(input, '.ts');
const code = {
input,
output: {
dir: './dist',
entryFileNames: `${name}.mjs`,
chunkFileNames: '[name]-[hash].mjs',
format: 'esm',
},
plugins: [
resolve(),
commonjs(),
esbuild({
target: 'node22', // 目标为 Node.js 14
minify: false, // 启用代码压缩
tsconfig: 'tsconfig.json',
}),
json(),
],
external: [],
};
const codeDts = {
input,
output: {
file: `./dist/${name}.d.ts`,
format: 'esm',
},
plugins: [dts()],
};
return [code, codeDts];
});
const allConfigs = configs.flat();
export default [config, dtsConfig, program, ...allConfigs];

View File

@ -0,0 +1,19 @@
import typescript from '@rollup/plugin-typescript';
import resolve from '@rollup/plugin-node-resolve';
import commonjs from '@rollup/plugin-commonjs';
import { dts } from 'rollup-plugin-dts';
import json from '@rollup/plugin-json';
import alias from '@rollup/plugin-alias';
import esbuild from 'rollup-plugin-esbuild';
import replace from '@rollup/plugin-replace';
import * as glob from 'glob';
import { nodeEntries } from './plugin-alias-config.ts';
export { glob };
// default export
export { typescript, resolve, commonjs, dts, json, alias, esbuild, replace };
// named export
export { nodeEntries };

View File

@ -0,0 +1,68 @@
import { program, Command } from '../program.ts';
import { fileIsExist } from '../utils/file.ts';
import path from 'path';
import fs from 'fs';
import { Chalk } from 'chalk';
const chalk = new Chalk({ level: 3 });
const createDevDependencies = (newJson: any) => {
let change = false;
if (newJson.devDependencies) {
change = true;
newJson.devDependencies = {
...newJson.devDependencies,
'@rollup/plugin-alias': '^5.1.1',
'@rollup/plugin-commonjs': '^28.0.1',
'@rollup/plugin-json': '^6.1.0',
'@rollup/plugin-node-resolve': '^15.3.0',
'@rollup/plugin-replace': '^6.0.1',
'@rollup/plugin-typescript': '^12.1.1',
'@types/node': '^22.9.0',
chalk: '^5.3.0',
commander: '^12.1.0',
glob: '^11.0.0',
rollup: '^4.26.0',
'rollup-plugin-copy': '^3.5.0',
'rollup-plugin-dts': '^6.1.1',
'rollup-plugin-esbuild': '^6.1.1',
'rollup-plugin-inject': '^3.0.2',
tslib: '^2.8.1',
typescript: '^5.6.2',
};
}
return { json: newJson, change };
};
const command = new Command('init').description('Create a new package or update package').action(async () => {
const runPath = process.cwd();
const packageJsonPath = path.resolve(runPath, 'package.json');
if (fileIsExist(packageJsonPath)) {
const json = fs.readFileSync(packageJsonPath, 'utf-8');
try {
const newJson = JSON.parse(json);
const { json: _json, change } = createDevDependencies(newJson);
if (change) {
fs.writeFileSync(packageJsonPath, JSON.stringify(_json, null, 2));
console.log(chalk.green('package.json updated'));
}
} catch (e) {
console.log(chalk.red('package.json is invalid'));
}
} else {
const newJson = {
name: 'new-package',
version: '1.0.0',
main: 'dist/index.js',
module: 'dist/index.mjs',
types: 'dist/index.d.ts',
scripts: {
build: 'rollup -c',
watch: 'rollup -c w',
},
devDependencies: {},
};
const { json, change } = createDevDependencies(newJson);
fs.writeFileSync(packageJsonPath, JSON.stringify(json, null, 2));
console.log(chalk.green('package.json created'));
}
});
program.addCommand(command);

View File

@ -0,0 +1,22 @@
export const nodeEntries = [
{ find: 'http', replacement: 'node:http' },
{ find: 'https', replacement: 'node:https' },
{ find: 'fs', replacement: 'node:fs' },
{ find: 'path', replacement: 'node:path' },
{ find: 'crypto', replacement: 'node:crypto' },
{ find: 'zlib', replacement: 'node:zlib' },
{ find: 'stream', replacement: 'node:stream' },
{ find: 'net', replacement: 'node:net' },
{ find: 'tty', replacement: 'node:tty' },
{ find: 'tls', replacement: 'node:tls' },
{ find: 'buffer', replacement: 'node:buffer' },
{ find: 'timers', replacement: 'node:timers' },
// { find: 'string_decoder', replacement: 'node:string_decoder' },
{ find: 'dns', replacement: 'node:dns' },
{ find: 'domain', replacement: 'node:domain' },
{ find: 'os', replacement: 'node:os' },
{ find: 'events', replacement: 'node:events' },
{ find: 'url', replacement: 'node:url' },
{ find: 'assert', replacement: 'node:assert' },
{ find: 'util', replacement: 'node:util' },
];

View File

@ -0,0 +1,3 @@
export const banner = `import { fileURLToPath as fileURLToPath2, pathToFileURL as pathToFileURL2} from 'url';
const __filename = fileURLToPath2(import.meta.url);
const __dirname = dirname(__filename);`;

View File

@ -0,0 +1,114 @@
import * as rollup from 'rollup';
import { program, Command } from 'commander';
import path from 'path';
import { fileIsExist } from './utils/file.ts';
import { resolve, commonjs, nodeEntries, alias, esbuild, json } from './app.ts';
import { Chalk } from 'chalk';
const chalk = new Chalk({ level: 3 });
const green = chalk.green;
const blue = chalk.blue;
export async function build(rollupConfig: rollup.RollupOptions) {
const bundle = await rollup.rollup(rollupConfig);
const startTime = Date.now();
const output = rollupConfig.output as rollup.OutputOptions;
const dir = output?.dir || 'dist';
const entry = process.cwd();
const { output: outputFiles } = await bundle.write(output);
outputFiles.forEach((file) => {
let filePath = path.resolve(entry, dir, file.fileName);
// @ts-ignore
let relativefilePath = path.relative(entry, file.facadeModuleId);
let relativeOutputPath = path.relative(entry, filePath);
console.log(blue(`${relativefilePath}${relativeOutputPath}`));
});
await bundle.close();
console.log(green(`created ${dir} in ${Date.now() - startTime}ms`));
}
export async function rollupWatch(rollupConfig: rollup.RollupOptions) {
const watcher = rollup.watch(rollupConfig);
watcher.on('event', (event) => {
if (event.code === 'START') {
console.log(chalk.bold('Rebuilding...'));
} else if (event.code === 'BUNDLE_END') {
console.log(chalk.green(`Bundled in ${event.duration}ms.`));
} else if (event.code === 'END') {
console.log(chalk.whiteBright('Watching for changes...'));
} else if (event.code === 'ERROR') {
console.error(chalk.red('Error:', event.error));
}
});
}
// 将多个子命令加入主程序中
program.name('system-apps').description('A CLI tool with envison backend services').version('0.0.1');
const defaultConfig = {
input: 'src/index.ts',
output: {
file: 'dist/index.mjs',
chunkFileNames: '[name]-[hash].mjs',
format: 'esm',
},
plugins: [
// @ts-ignore
alias({ entries: [{ find: '@', replacement: path.resolve('src') }, ...nodeEntries] }),
// @ts-ignore
resolve(),
// @ts-ignore
commonjs(),
esbuild({
target: 'node22', // 目标为 Node.js 14
minify: false, // 启用代码压缩
tsconfig: 'tsconfig.json',
}),
// @ts-ignore
json(),
],
};
const runBuild = new Command('build')
.option('-c --config <config>', 'config path')
.option('-w --watch ', 'watch ')
.description('Build the project')
.action(async (options) => {
const { config, watch } = options;
const runPath = process.cwd();
const configRelativePath = config || `rollup.config.mjs`;
const configPath = path.resolve(runPath, configRelativePath);
let configs = [];
if (fileIsExist(configPath)) {
const config = await import(configPath);
if (!config.default) {
throw new Error('config file must have a default export');
}
configs = Array.isArray(config.default) ? config.default : [config.default];
} else {
configs.push(defaultConfig);
}
if (watch) {
configs = configs.map((config: rollup.RollupOptions) => {
config.watch = {
buildDelay: 100,
clearScreen: false,
include: 'src/**',
...config.watch,
};
return config;
});
for (const config of configs) {
await rollupWatch(config);
}
} else {
for (const config of configs) {
await build(config);
}
}
});
program.addCommand(runBuild);
export { program, Command };

View File

@ -0,0 +1,8 @@
import { program } from './program.ts';
// program.parse(process.argv);
import './command/new-package.ts';
export const runParser = async (argv: string[]) => {
// program.parse(process.argv);
program.parse(argv);
};

View File

@ -0,0 +1,9 @@
import fs from 'fs';
export const fileIsExist = (filePath: string) => {
try {
fs.accessSync(filePath, fs.constants.F_OK);
return true;
} catch (error) {
return false;
}
};

View File

@ -0,0 +1,36 @@
{
"compilerOptions": {
"module": "nodenext",
"target": "esnext",
"noImplicitAny": false,
"outDir": "./dist",
"sourceMap": false,
"allowJs": true,
"newLine": "LF",
"baseUrl": "./",
"typeRoots": [
"node_modules/@types",
],
"declaration": true,
"noEmit": false,
"allowImportingTsExtensions": true,
"emitDeclarationOnly": true,
"moduleResolution": "NodeNext",
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
"esModuleInterop": true,
"paths": {
"@/*": [
"src/*"
]
}
},
"include": [
"src/**/*.ts",
"test/**/*.ts",
],
"exclude": [
"node_modules",
"dist"
],
}

66
pnpm-lock.yaml generated
View File

@ -154,6 +154,60 @@ importers:
specifier: 5.0.0-rc.2
version: 5.0.0-rc.2(@types/react@18.3.11)(immer@10.1.1)(react@18.3.1)
packages/rollup-tools:
dependencies:
'@rollup/plugin-alias':
specifier: ^5.1.1
version: 5.1.1(rollup@4.26.0)
'@rollup/plugin-commonjs':
specifier: ^28.0.1
version: 28.0.1(rollup@4.26.0)
'@rollup/plugin-json':
specifier: ^6.1.0
version: 6.1.0(rollup@4.26.0)
'@rollup/plugin-node-resolve':
specifier: ^15.3.0
version: 15.3.0(rollup@4.26.0)
'@rollup/plugin-replace':
specifier: ^6.0.1
version: 6.0.1(rollup@4.26.0)
'@rollup/plugin-typescript':
specifier: ^12.1.1
version: 12.1.1(rollup@4.26.0)(tslib@2.8.1)(typescript@5.6.3)
'@types/node':
specifier: ^22.9.0
version: 22.9.0
chalk:
specifier: ^5.3.0
version: 5.3.0
commander:
specifier: ^12.1.0
version: 12.1.0
glob:
specifier: ^11.0.0
version: 11.0.0
rollup:
specifier: ^4.26.0
version: 4.26.0
rollup-plugin-copy:
specifier: ^3.5.0
version: 3.5.0
rollup-plugin-dts:
specifier: ^6.1.1
version: 6.1.1(rollup@4.26.0)(typescript@5.6.3)
rollup-plugin-esbuild:
specifier: ^6.1.1
version: 6.1.1(esbuild@0.23.1)(rollup@4.26.0)
rollup-plugin-inject:
specifier: ^3.0.2
version: 3.0.2
tslib:
specifier: ^2.8.1
version: 2.8.1
typescript:
specifier: ^5.6.2
version: 5.6.3
services/apps-backend-store:
dependencies:
'@abearxiong/auth':
@ -1631,6 +1685,10 @@ packages:
resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==}
engines: {node: '>=10'}
chalk@5.3.0:
resolution: {integrity: sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==}
engines: {node: ^12.17.0 || ^14.13 || >=16.0.0}
character-entities@2.0.2:
resolution: {integrity: sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==}
@ -1698,6 +1756,10 @@ packages:
colorette@2.0.20:
resolution: {integrity: sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==}
commander@12.1.0:
resolution: {integrity: sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==}
engines: {node: '>=18'}
commander@2.15.1:
resolution: {integrity: sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==}
@ -5544,6 +5606,8 @@ snapshots:
ansi-styles: 4.3.0
supports-color: 7.2.0
chalk@5.3.0: {}
character-entities@2.0.2: {}
charm@0.1.2: {}
@ -5600,6 +5664,8 @@ snapshots:
colorette@2.0.20: {}
commander@12.1.0: {}
commander@2.15.1: {}
commander@2.20.3: {}

View File

@ -36,3 +36,5 @@ if (DEV_SERVER || !EXPORT_APP) {
console.log('pm2-manage is running on', `http://localhost:3006`);
});
}
//