diff --git a/README.md b/README.md index 136b2b95..20d9f2ba 100644 --- a/README.md +++ b/README.md @@ -169,6 +169,15 @@ esm 为 `rollup` 或 `babel` 时,等同于配置了 `{ type: "rollup" | "babel 通常不需要配置,除非你发布到 npm 的代码需要保密。 +#### esm.importLibToEs + +是否在 esm 模式下把 import 项里的 `/lib/` 转换为 `/es/`。 + +* Type: `boolean` +* Default: `false` + +比如 `import 'foo/lib/button';`,在 cjs 模式下会保持原样,在 esm 模式下会编译成 `import 'foo/es/button';`。 + #### cjs 是否输出 cjs 格式,以及指定 cjs 格式的打包方式等。 diff --git a/src/babel.ts b/src/babel.ts index f4777f28..ac9fbde2 100644 --- a/src/babel.ts +++ b/src/babel.ts @@ -17,6 +17,7 @@ interface IBabelOpts { type: 'esm' | 'cjs'; target?: 'browser' | 'node'; watch?: boolean; + importLibToEs?: boolean; bundleOpts: IBundleOptions; } @@ -33,6 +34,7 @@ export default async function(opts: IBabelOpts) { cwd, type, watch, + importLibToEs, bundleOpts: { target = 'browser', runtimeHelpers, @@ -63,6 +65,9 @@ export default async function(opts: IBabelOpts) { browserFiles, nodeFiles, }); + if (importLibToEs && type === 'esm') { + babelOpts.plugins.push(require.resolve('../lib/importLibToEs')); + } babelOpts.presets.push(...extraBabelPresets); babelOpts.plugins.push(...extraBabelPlugins); diff --git a/src/build.ts b/src/build.ts index 687c7b36..58e5747e 100644 --- a/src/build.ts +++ b/src/build.ts @@ -119,13 +119,15 @@ export async function build(opts: IOpts, extraOpts: IExtraBuildOpts = {}) { if (bundleOpts.esm) { const esm = bundleOpts.esm as IEsm; log(`Build esm with ${esm.type}`); + const importLibToEs = esm && esm.importLibToEs; if (esm && esm.type === 'babel') { - await babel({ cwd, watch, type: 'esm', bundleOpts }); + await babel({ cwd, watch, type: 'esm', importLibToEs, bundleOpts }); } else { await rollup({ cwd, type: 'esm', entry: bundleOpts.entry, + importLibToEs, watch, bundleOpts, }); diff --git a/src/fixtures/build/babel-importLibToEs/.umirc.library.js b/src/fixtures/build/babel-importLibToEs/.umirc.library.js new file mode 100644 index 00000000..f1ef9292 --- /dev/null +++ b/src/fixtures/build/babel-importLibToEs/.umirc.library.js @@ -0,0 +1,5 @@ + +export default { + cjs: { type: 'babel' }, + esm: { type: 'babel', importLibToEs: true }, +}; diff --git a/src/fixtures/build/babel-importLibToEs/expected/es/index.js b/src/fixtures/build/babel-importLibToEs/expected/es/index.js new file mode 100644 index 00000000..d10ef273 --- /dev/null +++ b/src/fixtures/build/babel-importLibToEs/expected/es/index.js @@ -0,0 +1,2 @@ +import foo from "foo/es/foo"; +console.log(foo()); \ No newline at end of file diff --git a/src/fixtures/build/babel-importLibToEs/expected/lib/index.js b/src/fixtures/build/babel-importLibToEs/expected/lib/index.js new file mode 100644 index 00000000..6e3881ac --- /dev/null +++ b/src/fixtures/build/babel-importLibToEs/expected/lib/index.js @@ -0,0 +1,7 @@ +"use strict"; + +var _foo = _interopRequireDefault(require("foo/lib/foo")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +console.log((0, _foo.default)()); \ No newline at end of file diff --git a/src/fixtures/build/babel-importLibToEs/node_modules/foo/es/foo.js b/src/fixtures/build/babel-importLibToEs/node_modules/foo/es/foo.js new file mode 100644 index 00000000..af8e0b19 --- /dev/null +++ b/src/fixtures/build/babel-importLibToEs/node_modules/foo/es/foo.js @@ -0,0 +1,4 @@ + +export default function () { + return 'es/foo'; +} diff --git a/src/fixtures/build/babel-importLibToEs/node_modules/foo/lib/foo.js b/src/fixtures/build/babel-importLibToEs/node_modules/foo/lib/foo.js new file mode 100644 index 00000000..d6f486d0 --- /dev/null +++ b/src/fixtures/build/babel-importLibToEs/node_modules/foo/lib/foo.js @@ -0,0 +1,4 @@ + +export default function () { + return 'lib/foo'; +} diff --git a/src/fixtures/build/babel-importLibToEs/node_modules/foo/package.json b/src/fixtures/build/babel-importLibToEs/node_modules/foo/package.json new file mode 100644 index 00000000..fab6d24b --- /dev/null +++ b/src/fixtures/build/babel-importLibToEs/node_modules/foo/package.json @@ -0,0 +1,4 @@ +{ + "name": "foo", + "version": "0.1.0" +} diff --git a/src/fixtures/build/babel-importLibToEs/src/index.js b/src/fixtures/build/babel-importLibToEs/src/index.js new file mode 100644 index 00000000..a8105c42 --- /dev/null +++ b/src/fixtures/build/babel-importLibToEs/src/index.js @@ -0,0 +1,3 @@ +import foo from 'foo/lib/foo'; + +console.log(foo()); diff --git a/src/fixtures/build/rollup-importLibToEs/.umirc.library.js b/src/fixtures/build/rollup-importLibToEs/.umirc.library.js new file mode 100644 index 00000000..2881eb58 --- /dev/null +++ b/src/fixtures/build/rollup-importLibToEs/.umirc.library.js @@ -0,0 +1,5 @@ + +export default { + cjs: { type: 'rollup' }, + esm: { type: 'rollup', importLibToEs: true }, +}; diff --git a/src/fixtures/build/rollup-importLibToEs/expected/index.esm.js b/src/fixtures/build/rollup-importLibToEs/expected/index.esm.js new file mode 100644 index 00000000..ae0559b1 --- /dev/null +++ b/src/fixtures/build/rollup-importLibToEs/expected/index.esm.js @@ -0,0 +1,5 @@ +function foo () { + return 'es/foo'; +} + +console.log(foo()); diff --git a/src/fixtures/build/rollup-importLibToEs/expected/index.js b/src/fixtures/build/rollup-importLibToEs/expected/index.js new file mode 100644 index 00000000..c4e33e77 --- /dev/null +++ b/src/fixtures/build/rollup-importLibToEs/expected/index.js @@ -0,0 +1,7 @@ +'use strict'; + +function foo () { + return 'lib/foo'; +} + +console.log(foo()); diff --git a/src/fixtures/build/rollup-importLibToEs/node_modules/foo/es/foo.js b/src/fixtures/build/rollup-importLibToEs/node_modules/foo/es/foo.js new file mode 100644 index 00000000..af8e0b19 --- /dev/null +++ b/src/fixtures/build/rollup-importLibToEs/node_modules/foo/es/foo.js @@ -0,0 +1,4 @@ + +export default function () { + return 'es/foo'; +} diff --git a/src/fixtures/build/rollup-importLibToEs/node_modules/foo/lib/foo.js b/src/fixtures/build/rollup-importLibToEs/node_modules/foo/lib/foo.js new file mode 100644 index 00000000..d6f486d0 --- /dev/null +++ b/src/fixtures/build/rollup-importLibToEs/node_modules/foo/lib/foo.js @@ -0,0 +1,4 @@ + +export default function () { + return 'lib/foo'; +} diff --git a/src/fixtures/build/rollup-importLibToEs/node_modules/foo/package.json b/src/fixtures/build/rollup-importLibToEs/node_modules/foo/package.json new file mode 100644 index 00000000..fab6d24b --- /dev/null +++ b/src/fixtures/build/rollup-importLibToEs/node_modules/foo/package.json @@ -0,0 +1,4 @@ +{ + "name": "foo", + "version": "0.1.0" +} diff --git a/src/fixtures/build/rollup-importLibToEs/src/index.js b/src/fixtures/build/rollup-importLibToEs/src/index.js new file mode 100644 index 00000000..a8105c42 --- /dev/null +++ b/src/fixtures/build/rollup-importLibToEs/src/index.js @@ -0,0 +1,3 @@ +import foo from 'foo/lib/foo'; + +console.log(foo()); diff --git a/src/getRollupConfig.ts b/src/getRollupConfig.ts index 2fda71ef..27d6f46c 100644 --- a/src/getRollupConfig.ts +++ b/src/getRollupConfig.ts @@ -19,6 +19,7 @@ interface IGetRollupConfigOpts { cwd: string; entry: string; type: ModuleFormat; + importLibToEs?: boolean; bundleOpts: IBundleOptions; } @@ -29,7 +30,7 @@ interface IPkg { } export default function(opts: IGetRollupConfigOpts): RollupOptions[] { - const { type, entry, cwd, bundleOpts } = opts; + const { type, entry, cwd, importLibToEs, bundleOpts } = opts; const { umd, esm, @@ -70,6 +71,9 @@ export default function(opts: IGetRollupConfigOpts): RollupOptions[] { // 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); diff --git a/src/importLibToEs.js b/src/importLibToEs.js new file mode 100644 index 00000000..e7d278a6 --- /dev/null +++ b/src/importLibToEs.js @@ -0,0 +1,26 @@ +import { join, dirname } from 'path'; +import fs from 'fs'; + +const cwd = process.cwd(); + +function replacePath(path) { + if (path.node.source && /\/lib\//.test(path.node.source.value)) { + const esModule = path.node.source.value.replace('/lib/', '/es/'); + const esPath = dirname(join(cwd, `node_modules/${esModule}`)); + if (fs.existsSync(esPath)) { + console.log(`[es build] replace ${path.node.source.value} with ${esModule}`); + path.node.source.value = esModule; + } + } +} + +function replaceLib() { + return { + visitor: { + ImportDeclaration: replacePath, + ExportNamedDeclaration: replacePath, + }, + }; +} + +export default replaceLib; diff --git a/src/rollup.ts b/src/rollup.ts index b53357e1..706d3e83 100644 --- a/src/rollup.ts +++ b/src/rollup.ts @@ -10,14 +10,16 @@ interface IRollupOpts { type: ModuleFormat; bundleOpts: IBundleOptions; watch?: boolean; + importLibToEs?: boolean; } async function build(entry: string, opts: IRollupOpts) { - const { cwd, type, bundleOpts } = opts; + const { cwd, type, bundleOpts, importLibToEs } = opts; const rollupConfigs = getRollupConfig({ cwd, type, entry, + importLibToEs, bundleOpts: normalizeBundleOpts(entry, bundleOpts), }); diff --git a/src/schema.ts b/src/schema.ts index b2ff1948..5306c3b8 100644 --- a/src/schema.ts +++ b/src/schema.ts @@ -23,6 +23,9 @@ export default { file: noEmptyStr, mjs: { type: 'boolean' }, minify: { type: 'boolean' }, + importLibToEs: { + type: 'boolean', + }, }, }, ], diff --git a/src/types.d.ts b/src/types.d.ts index c05398e9..62cde6b1 100644 --- a/src/types.d.ts +++ b/src/types.d.ts @@ -14,6 +14,7 @@ interface ICjs extends IBundleTypeOutput { interface IEsm extends IBundleTypeOutput { mjs?: boolean; minify?: boolean; + importLibToEs?: boolean; } interface IStringObject {