diff --git a/packages/bundler-esbuild/package.json b/packages/bundler-esbuild/package.json index 6adb8057b8d4..a50df3cdbafa 100644 --- a/packages/bundler-esbuild/package.json +++ b/packages/bundler-esbuild/package.json @@ -31,6 +31,7 @@ "dependencies": { "@umijs/bundler-utils": "4.0.0-beta.5", "@umijs/utils": "4.0.0-beta.5", + "enhanced-resolve": "5.8.3", "less": "4.1.2" }, "devDependencies": { diff --git a/packages/bundler-esbuild/src/build.test.ts b/packages/bundler-esbuild/src/build.test.ts index ac8d94e97d43..101b1cf20be2 100644 --- a/packages/bundler-esbuild/src/build.test.ts +++ b/packages/bundler-esbuild/src/build.test.ts @@ -10,8 +10,16 @@ const EXISTS = '1'; const expects: Record = { alias({ files }: IOpts) { - expect(files['index.js']).toContain(`var a = "react";`); - expect(files['index.js']).toContain(`var something = "happy";`); + // import('foo') > import ('/path/foo.js') + expect(files['index.js']).toContain(`console.log("foo");`); + // import('dir') > import ('/path/dir/index.js') + expect(files['index.js']).toContain(`console.log("dir");`); + // import('dir/bar') > import ('/path/dir/bar.js') + expect(files['index.js']).toContain(`console.log("bar");`); + // import('less') > import ('/path/less.ts') + expect(files['index.js']).toContain(`console.log("less");`); + // import('less/bower') > import ('less/bower.json') 没匹配上走默认 + expect(files['index.js']).toContain(`"dist/less.js"`); }, externals({ files }: IOpts) { expect(files['index.js']).toContain(`module.export = React;`); diff --git a/packages/bundler-esbuild/src/build.ts b/packages/bundler-esbuild/src/build.ts index 2e7fe3d99cf5..179305c386cb 100644 --- a/packages/bundler-esbuild/src/build.ts +++ b/packages/bundler-esbuild/src/build.ts @@ -44,7 +44,7 @@ export async function build(opts: IOpts) { javascriptEnabled: true, ...opts.config.lessLoader, }), - alias(opts.config.alias), + alias({ cwd: opts.cwd, ...opts.config.alias }), externals(opts.config.externals), ], define: { diff --git a/packages/bundler-esbuild/src/fixtures/alias/config.ts b/packages/bundler-esbuild/src/fixtures/alias/config.ts index e045249b64b9..e55ea4fdc1f4 100644 --- a/packages/bundler-esbuild/src/fixtures/alias/config.ts +++ b/packages/bundler-esbuild/src/fixtures/alias/config.ts @@ -1,7 +1,8 @@ import { join } from 'path'; export default { alias: { - react: require.resolve('./react.ts'), - some: join(__dirname,'some'), + foo: './path/foo', + dir: join(__dirname, 'path', 'dir'), + less$: join(__dirname, 'path', 'less'), }, }; diff --git a/packages/bundler-esbuild/src/fixtures/alias/index.ts b/packages/bundler-esbuild/src/fixtures/alias/index.ts index 3f32b7438605..ba5fe5a9ff5e 100644 --- a/packages/bundler-esbuild/src/fixtures/alias/index.ts +++ b/packages/bundler-esbuild/src/fixtures/alias/index.ts @@ -1,6 +1,15 @@ // @ts-ignore -import react from 'react'; +import less from 'less'; // @ts-ignore -import something from 'some/thing.ts'; -console.log(react); -console.log(something); +import bower from 'less/bower'; +// @ts-ignore +import foo from 'foo'; +// @ts-ignore +import dir from 'dir'; +// @ts-ignore +import bar from 'dir/bar'; +console.log(less); +console.log(bower); +console.log(foo); +console.log(bar); +console.log(dir); diff --git a/packages/bundler-esbuild/src/fixtures/alias/path/dir/bar.js b/packages/bundler-esbuild/src/fixtures/alias/path/dir/bar.js new file mode 100644 index 000000000000..8cc7aa3e902f --- /dev/null +++ b/packages/bundler-esbuild/src/fixtures/alias/path/dir/bar.js @@ -0,0 +1 @@ +console.log('bar'); diff --git a/packages/bundler-esbuild/src/fixtures/alias/path/dir/index.js b/packages/bundler-esbuild/src/fixtures/alias/path/dir/index.js new file mode 100644 index 000000000000..a687c5f52a67 --- /dev/null +++ b/packages/bundler-esbuild/src/fixtures/alias/path/dir/index.js @@ -0,0 +1 @@ +console.log('dir'); diff --git a/packages/bundler-esbuild/src/fixtures/alias/path/foo.js b/packages/bundler-esbuild/src/fixtures/alias/path/foo.js new file mode 100644 index 000000000000..81afa3157c18 --- /dev/null +++ b/packages/bundler-esbuild/src/fixtures/alias/path/foo.js @@ -0,0 +1 @@ +console.log('foo'); diff --git a/packages/bundler-esbuild/src/fixtures/alias/path/less.ts b/packages/bundler-esbuild/src/fixtures/alias/path/less.ts new file mode 100644 index 000000000000..d8eb14eb6b27 --- /dev/null +++ b/packages/bundler-esbuild/src/fixtures/alias/path/less.ts @@ -0,0 +1 @@ +console.log('less'); diff --git a/packages/bundler-esbuild/src/fixtures/alias/react.ts b/packages/bundler-esbuild/src/fixtures/alias/react.ts deleted file mode 100644 index 4e45e6b544de..000000000000 --- a/packages/bundler-esbuild/src/fixtures/alias/react.ts +++ /dev/null @@ -1,2 +0,0 @@ -const a = 'react'; -export default a; diff --git a/packages/bundler-esbuild/src/fixtures/alias/some/thing.ts b/packages/bundler-esbuild/src/fixtures/alias/some/thing.ts deleted file mode 100644 index 112357a19150..000000000000 --- a/packages/bundler-esbuild/src/fixtures/alias/some/thing.ts +++ /dev/null @@ -1,2 +0,0 @@ -const something = 'happy'; -export default something; diff --git a/packages/bundler-esbuild/src/plugins/alias.ts b/packages/bundler-esbuild/src/plugins/alias.ts index 6b8a677a8473..6a5927f4513f 100644 --- a/packages/bundler-esbuild/src/plugins/alias.ts +++ b/packages/bundler-esbuild/src/plugins/alias.ts @@ -1,5 +1,41 @@ import { Plugin } from '@umijs/bundler-utils/compiled/esbuild'; import { winPath } from '@umijs/utils'; +import assert from 'assert'; +import enhancedResolve from 'enhanced-resolve'; +import { dirname } from 'path'; + +const getRealFile = async (cwd: string, file: string) => { + try { + return await resolve(cwd, file); + } catch (e) { + return null; + } +}; +const resolver = enhancedResolve.create({ + mainFields: ['module', 'browser', 'main'], + extensions: [ + '.json', + '.js', + '.jsx', + '.ts', + '.tsx', + '.cjs', + '.mjs', + '.cjsx', + '.mjsx', + ], + // TODO: support exports + // tried to add exports, but it don't work with swr + exportsFields: [], +}); + +async function resolve(context: string, path: string): Promise { + return new Promise((resolve, reject) => { + resolver(context, path, (err: Error, result: string) => + err ? reject(err) : resolve(result), + ); + }); +} // https://esbuild.github.io/plugins/#resolve-callbacks export default (options?: Record): Plugin => { @@ -10,24 +46,27 @@ export default (options?: Record): Plugin => { return; } Object.keys(options).forEach((key) => { - // import react from 'react'; - onResolve({ filter: new RegExp(`^${key}$`) }, (args) => { - return { - path: winPath(args.path).replace( - new RegExp(`^${key}$`), - options[key], - ), - }; - }); - // import abc from 'react/abc'; - // import abc from 'react/abc.js'; - onResolve({ filter: new RegExp(`^${key}\\/.*$`) }, (args) => { - return { - path: winPath(args.path).replace( - new RegExp(`^${key}`), - options[key], - ), - }; + onResolve({ filter: new RegExp(`^${key}`) }, async (args) => { + const dir = dirname(args.path); + try { + const realFile = await getRealFile( + options.cwd, + winPath(args.path).replace(new RegExp(`^${key}`), options[key]), + ); + assert(realFile, `filePath not found of ${args.path}`); + return { + path: realFile, + }; + } catch (error: any) { + return { + errors: [ + { + text: error.message, + }, + ], + resolveDir: dir, + }; + } }); }); }, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 2a8df0e9f0fc..4c18d856b657 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -62,6 +62,9 @@ importers: umi: link:packages/umi zx: 4.2.0 + examples/ant-design-pro: + specifiers: {} + examples/boilerplate: specifiers: {} @@ -132,10 +135,12 @@ importers: '@types/less': ^3.0.3 '@umijs/bundler-utils': 4.0.0-beta.5 '@umijs/utils': 4.0.0-beta.5 + enhanced-resolve: 5.8.3 less: 4.1.2 dependencies: '@umijs/bundler-utils': link:../bundler-utils '@umijs/utils': link:../utils + enhanced-resolve: 5.8.3 less: 4.1.2 devDependencies: '@types/less': 3.0.3 @@ -7473,7 +7478,6 @@ packages: dependencies: graceful-fs: 4.2.8 tapable: 2.2.1 - dev: true /enquirer/2.3.6: resolution: {integrity: sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==} @@ -14442,7 +14446,6 @@ packages: /tapable/2.2.1: resolution: {integrity: sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==} engines: {node: '>=6'} - dev: true /tar/4.4.19: resolution: {integrity: sha512-a20gEsvHnWe0ygBY8JbxoM4w3SJdhc7ZAuxkLqh+nvNQN2IOt0B5lLgM490X5Hl8FF0dl0tOf2ewFYAlIFgzVA==}