tachybase_todo/packages/core/build/src/getRollupConfig.ts

344 lines
11 KiB
TypeScript
Raw Normal View History

feat: build, cli, devtools, sdk, docs... * feat: nocobase build * chore: update build scripts * chore: update build scripts * chore(versions): 😊 publish v0.7.0-alpha.33 * chore: independent version * chore: nocobase build * chore(versions): 😊 publish v0.7.0-alpha.34 * feat: nocobase-cli * feat: nocobase-cli * chore: update dependencies * feat: improve code * refactor: create-nocobase-app * chore(versions): 😊 publish v0.7.0-alpha.35 * feat: @nocobase/devtools * chore(versions): 😊 publish v0.7.0-alpha.36 * chore: update dependencies * chore(versions): 😊 publish v0.7.0-alpha.37 * feat: improve code * chore(versions): 😊 publish v0.7.0-alpha.38 * feat: improve code * chore(versions): 😊 publish v0.7.0-alpha.39 * feat: update deps * chore(versions): 😊 publish v0.7.0-alpha.40 * chore: update devDependencies * chore(versions): 😊 publish v0.7.0-alpha.41 * fix: postinstall * chore(versions): 😊 publish v0.7.0-alpha.42 * chore: improve code * chore(versions): 😊 publish v0.7.0-alpha.43 * chore: execa * chore(versions): 😊 publish v0.7.0-alpha.44 * chore(cli): allow unknown option * chore(versions): 😊 publish v0.7.0-alpha.45 * fix: default envs * chore(versions): 😊 publish v0.7.0-alpha.45 * fix: package argument for build command * chore(versions): 😊 publish v0.7.0-alpha.46 * fix: improve code * chore(versions): 😊 publish v0.7.0-alpha.48 * feat: clean & doc * chore(versions): 😊 publish v0.7.0-alpha.49 * feat: compilation tips * feat: upgrade command * chore(versions): 😊 publish v0.7.0-alpha.50 * fix: unexpected token ] in JSON * chore(versions): 😊 publish v0.7.0-alpha.51 * fix: upgrade command * chore(versions): 😊 publish v0.7.0-alpha.52 * fix: remove export action from available action * fix: db sync after upgrade * chore(versions): 😊 publish v0.7.0-alpha.53 * feat: upgrade log * chore(versions): 😊 publish v0.7.0-alpha.54 * docs: updates * feat: updates * docs(cli): update usage description * feat: updates * docs: updates * docs: updates * docs: toc * feat: sdk * docs: updates * docs: updates * docs: updates * Update index.md * docs: updates * Update release-notes.md * Update roadmap.md * Update index.md * Update contributing.md * Update contributing.md * Update index.md * Update index.md * Update nocobase-cli.md * Update nocobase-cli.md * fix: user plugin initialization data * Update env.md * Update env.md * Update directory-structure.md * Update index.md * Update action-api.md * Update filter-operators.md * docs: update thanks.md * Update index.md * Update javascript-sdk.md * Update rest-api.md * Update installation.md * Update installation.md * Update upgrading.md * Update upgrading.md * Update upgrading.md * Update installation.md * Update installation.md * Create release-notes.md * Update release-notes.md * feat: updates * feat: update docs * feat: update release-notes.md * feat: switch language * feat: updates * Add files via upload * Add files via upload * Update important-features.md * Update thanks.md * feat: nocobase postinstall * Update index.md * Create why-different.md * Update why-different.md * Create who-is-for.md * Rename who-is-for.md to who.md * feat: update docs * Rename why-different.md to why.md * Update why.md * Update menus.ts * Update why-nocobase.md * Create who.md * Create why.md * feat: updates * chore(versions): 😊 publish v0.7.0-alpha.55 * feat: tips * Update who.md * Update who.md * feat: update docs * feat: update doc menus * fix: plugin client dist * docs: update contributing.md * docs: update readme.md * docs: update readme.md * docs: update readme.md * Update functional-zoning.md * fix: br Co-authored-by: Zhou <zhou.working@gmail.com>
2022-05-19 00:40:55 +08:00
import { existsSync } from 'fs'
import { basename, extname, join } from 'path';
import { ModuleFormat, RollupOptions, Plugin } from 'rollup';
import url from '@rollup/plugin-url';
import json from '@rollup/plugin-json';
import replace from '@rollup/plugin-replace';
import commonjs from '@rollup/plugin-commonjs';
import nodeResolve from '@rollup/plugin-node-resolve';
import inject, { RollupInjectOptions } from '@rollup/plugin-inject';
import babel, { RollupBabelInputPluginOptions } from '@rollup/plugin-babel';
import { createFilter } from '@rollup/pluginutils';
import postcss from 'rollup-plugin-postcss';
import { terser } from 'rollup-plugin-terser';
import typescript2 from 'rollup-plugin-typescript2';
import { camelCase } from 'lodash';
import tempDir from 'temp-dir';
import autoprefixer from 'autoprefixer';
import NpmImport from 'less-plugin-npm-import';
import svgr from '@svgr/rollup';
import getBabelConfig from './getBabelConfig';
import { getPkgPath, shouldTransform } from './es5ImcompatibleVersions';
import { IBundleOptions } from './types';
interface IGetRollupConfigOpts {
cwd: string;
rootPath: string;
entry: string;
type: ModuleFormat;
importLibToEs?: boolean;
bundleOpts: IBundleOptions;
}
interface IPkg {
dependencies?: Object;
peerDependencies?: Object;
name?: string;
}
export default function(opts: IGetRollupConfigOpts): RollupOptions[] {
const { type, entry, cwd, rootPath, importLibToEs, bundleOpts } = opts;
const {
umd,
esm,
cjs,
file,
target = 'browser',
extractCSS = false,
injectCSS = true,
cssModules: modules,
extraPostCSSPlugins = [],
extraBabelPresets = [],
extraBabelPlugins = [],
extraRollupPlugins = [],
autoprefixer: autoprefixerOpts,
include = /node_modules/,
runtimeHelpers: runtimeHelpersOpts,
replace: replaceOpts,
inject: injectOpts,
extraExternals = [],
externalsExclude = [],
nodeVersion,
typescriptOpts,
nodeResolveOpts = {},
disableTypeCheck,
lessInRollupMode = {},
sassInRollupMode = {},
} = bundleOpts;
const entryExt = extname(entry);
const name = file || basename(entry, entryExt);
const isTypeScript = entryExt === '.ts' || entryExt === '.tsx';
const extensions = ['.js', '.jsx', '.ts', '.tsx', '.es6', '.es', '.mjs'];
let pkg = {} as IPkg;
try {
pkg = require(join(cwd, 'package.json')); // eslint-disable-line
} catch (e) {}
// cjs 不给浏览器用,所以无需 runtimeHelpers
const runtimeHelpers = type === 'cjs' ? false : runtimeHelpersOpts;
const babelOpts = {
...(getBabelConfig({
type,
target: type === 'esm' ? 'browser' : target,
// watch 模式下有几率走的 babel原因未知。
// ref: https://github.com/umijs/father/issues/158
typescript: true,
runtimeHelpers,
nodeVersion,
}).opts),
// ref: https://github.com/rollup/plugins/tree/master/packages/babel#babelhelpers
babelHelpers: (runtimeHelpers ? 'runtime' : 'bundled') as RollupBabelInputPluginOptions['babelHelpers'],
// exclude: /\/node_modules\//,
filter: (filePath: string) => {
const rollupFilter = createFilter(null, /\/node_modules\//);
// 默认过滤 node_modules
if (!rollupFilter(filePath)) {
const pkgPath = getPkgPath(filePath);
return shouldTransform(pkgPath);
}
return true;
},
babelrc: false,
// ref: https://github.com/rollup/rollup-plugin-babel#usage
extensions,
};
if (importLibToEs && type === 'esm') {
babelOpts.plugins.push(require.resolve('../lib/importLibToEs'));
}
babelOpts.presets.push(...extraBabelPresets);
babelOpts.plugins.push(...extraBabelPlugins);
// rollup configs
const input = join(cwd, entry);
const format = type;
// ref: https://rollupjs.org/guide/en#external
// 潜在问题:引用包的子文件时会报 warning比如 @babel/runtime/helpers/esm/createClass
// 解决方案:可以用 function 处理
const external = [
...Object.keys(pkg.dependencies || {}),
...Object.keys(pkg.peerDependencies || {}),
...extraExternals,
];
// umd 只要 external peerDependencies
const externalPeerDeps = [
...Object.keys(pkg.peerDependencies || {}),
...extraExternals,
];
function getPkgNameByid(id) {
const splitted = id.split('/');
// @ 和 @tmp 是为了兼容 umi 的逻辑
if (id.charAt(0) === '@' && splitted[0] !== '@' && splitted[0] !== '@tmp') {
return splitted
.slice(0, 2)
.join('/');
} else {
return id.split('/')[0];
}
}
function testExternal(pkgs, excludes, id) {
if (excludes.includes(id)) {
return false;
}
return pkgs.includes(getPkgNameByid(id));
}
const terserOpts = {
compress: {
pure_getters: true,
unsafe: true,
unsafe_comps: true,
warnings: false,
},
};
// https://github.com/umijs/father/issues/164
function mergePlugins(defaultRollupPlugins: Array<Plugin> = [], extraRollupPlugins: Array<Plugin> = []) {
const pluginsMap: Record<string, Plugin> = Object.assign(
defaultRollupPlugins.reduce((r, plugin) => ({ ...r, [plugin.name]: plugin }), {}),
extraRollupPlugins.reduce((r, plugin) => ({ ...r, [plugin.name]: plugin }), {}),
);
return Object.values(pluginsMap);
}
function getPlugins(opts = {} as { minCSS: boolean; }) {
const { minCSS } = opts;
const defaultRollupPlugins = [
url(),
svgr(),
postcss({
extract: extractCSS,
inject: injectCSS,
modules,
// modules => all .less will convert into css modules
...(modules ? { autoModules: false } : {}),
minimize: !!minCSS,
use: {
less: {
plugins: [new NpmImport({ prefix: '~' })],
javascriptEnabled: true,
...lessInRollupMode
},
sass: {
...sassInRollupMode,
},
stylus: false,
},
plugins: [autoprefixer({
// https://github.com/postcss/autoprefixer/issues/776
remove: false,
...autoprefixerOpts,
}), ...extraPostCSSPlugins],
}),
...(injectOpts ? [inject(injectOpts as RollupInjectOptions)] : []),
...(replaceOpts && Object.keys(replaceOpts || {}).length ? [replace(replaceOpts)] : []),
nodeResolve({
mainFields: ['module', 'jsnext:main', 'main'],
extensions,
...nodeResolveOpts,
}),
...(isTypeScript
? [
typescript2({
cwd,
// @see https://github.com/umijs/father/issues/61#issuecomment-544822774
clean: true,
cacheRoot: `${tempDir}/.rollup_plugin_typescript2_cache`,
// 支持往上找 tsconfig.json
// 比如 lerna 的场景不需要每个 package 有个 tsconfig.json
tsconfig: [join(cwd, 'tsconfig.json'), join(rootPath, 'tsconfig.json')].find(existsSync),
tsconfigDefaults: {
compilerOptions: {
// Generate declaration files by default
declaration: true,
},
},
tsconfigOverride: {
compilerOptions: {
// Support dynamic import
target: 'esnext',
},
},
check: !disableTypeCheck,
...(typescriptOpts || {}),
}),
]
: []),
babel(babelOpts),
json(),
];
return mergePlugins(defaultRollupPlugins, extraRollupPlugins || []);
}
switch (type) {
case 'esm':
const output: Record<string, any> = {
dir: join(cwd, `${esm && (esm as any).dir || 'dist'}`),
entryFileNames: `${(esm && (esm as any).file) || `${name}.esm`}.js`,
}
return [
{
input,
output: {
format,
...output,
},
plugins: [...getPlugins(), ...(esm && (esm as any).minify ? [terser(terserOpts)] : [])],
external: testExternal.bind(null, external, externalsExclude),
},
...(esm && (esm as any).mjs
? [
{
input,
output: {
format,
file: join(cwd, `dist/${(esm && (esm as any).file) || `${name}`}.mjs`),
},
plugins: [
...getPlugins(),
replace({
'process.env.NODE_ENV': JSON.stringify('production'),
}),
terser(terserOpts),
],
external: testExternal.bind(null, externalPeerDeps, externalsExclude),
},
]
: []),
];
case 'cjs':
return [
{
input,
output: {
format,
file: join(cwd, `dist/${(cjs && (cjs as any).file) || name}.js`),
},
plugins: [...getPlugins(), ...(cjs && (cjs as any).minify ? [terser(terserOpts)] : [])],
external: testExternal.bind(null, external, externalsExclude),
},
];
case 'umd':
// Add umd related plugins
const extraUmdPlugins = [
commonjs({
include,
// namedExports options has been remove from https://github.com/rollup/plugins/pull/149
}),
];
return [
{
input,
output: {
format,
sourcemap: umd && umd.sourcemap,
file: join(cwd, `dist/${(umd && umd.file) || `${name}.umd`}.js`),
globals: umd && umd.globals,
name: (umd && umd.name) || (pkg.name && camelCase(basename(pkg.name))),
},
plugins: [
...extraUmdPlugins,
...getPlugins(),
replace({
'process.env.NODE_ENV': JSON.stringify('development'),
}),
],
external: testExternal.bind(null, externalPeerDeps, externalsExclude),
},
...(umd && umd.minFile === false
? []
: [
{
input,
output: {
format,
sourcemap: umd && umd.sourcemap,
file: join(cwd, `dist/${(umd && umd.file) || `${name}.umd`}.min.js`),
globals: umd && umd.globals,
name: (umd && umd.name) || (pkg.name && camelCase(basename(pkg.name))),
},
plugins: [
...extraUmdPlugins,
...getPlugins({ minCSS: true }),
replace({
'process.env.NODE_ENV': JSON.stringify('production'),
}),
terser(terserOpts),
],
external: testExternal.bind(null, externalPeerDeps, externalsExclude),
},
]),
];
default:
throw new Error(`Unsupported type ${type}`);
}
}