diff --git a/packages/react/import-component/import-component-loader.js b/packages/react/import-component/import-component-loader.js deleted file mode 100644 index 7c6b84d175..0000000000 --- a/packages/react/import-component/import-component-loader.js +++ /dev/null @@ -1,11 +0,0 @@ -const regex = - /importComponent\s*\(\s*\(\)\s+=>\s+import\(\s*'([^']+)'\s*\)\s*\)/g; - -function importComponentLoader(source) { - return source.replace( - regex, - "importComponent({ load: () => import('$1'), moduleId: require.resolveWeak('$1') })" - ); -} - -module.exports = importComponentLoader; diff --git a/packages/react/import-component/mixin.core.js b/packages/react/import-component/mixin.core.js index 1a0fcbc4f0..32f7255b18 100644 --- a/packages/react/import-component/mixin.core.js +++ b/packages/react/import-component/mixin.core.js @@ -5,7 +5,7 @@ class ImportComponentCoreMixin extends Mixin { const { experimentalEsbuild } = this.options; if (experimentalEsbuild) { - jsLoaderConfig.use.push(require.resolve('./import-component-loader.js')); + jsLoaderConfig.use.push(require.resolve('./swc-loader.js')); } else { jsLoaderConfig.options.plugins.push([ require.resolve('../lib/babel'), diff --git a/packages/react/import-component/swc-ast-helper.js b/packages/react/import-component/swc-ast-helper.js new file mode 100644 index 0000000000..3ca41ad92d --- /dev/null +++ b/packages/react/import-component/swc-ast-helper.js @@ -0,0 +1,71 @@ +function createAstHelper(span = { start: 0, end: 0, ctxt: 0 }) { + const ast = { + IdentifierOrExpression: (subject) => { + if (typeof subject === 'string') { + return { + type: 'Identifier', + span, + value: subject, + optional: false, + }; + } else { + return subject; + } + }, + ObjectExpression: (properties) => { + return { + type: 'ObjectExpression', + span, + properties: Object.entries(properties).map(([key, value]) => { + return { + type: 'KeyValueProperty', + key: { + type: 'Identifier', + span, + value: key, + optional: false, + }, + value, + }; + }), + }; + }, + ArrowFunctionExpression: (body) => { + return { + type: 'ArrowFunctionExpression', + span, + params: [], + body, + }; + }, + CallExpression: (callee, ...args) => { + return { + type: 'CallExpression', + span, + callee: ast.IdentifierOrExpression(callee), + arguments: args.map((expression) => { + return { + spread: null, + expression, + }; + }), + typeArguments: null, + }; + }, + MemberExpression: (object, property) => { + return { + type: 'MemberExpression', + span, + object: ast.IdentifierOrExpression(object), + property: ast.IdentifierOrExpression(property), + computed: false, + }; + }, + }; + + return ast; +} + +module.exports = { + createAstHelper, +}; diff --git a/packages/react/import-component/swc-loader.js b/packages/react/import-component/swc-loader.js new file mode 100644 index 0000000000..74bd2b2404 --- /dev/null +++ b/packages/react/import-component/swc-loader.js @@ -0,0 +1,27 @@ +const { transformSync } = require('@swc/core'); +const { ImportComponentTransformer } = require('./swc-transformer'); + +function importComponentLoader(source, inputSourceMap) { + if (!/[^\w]importComponent\s*\(/.test(source)) return source; + + const { resourcePath: sourceFileName } = this; + const ts = /\.tsx?$/.test(sourceFileName); + const tsx = /\.tsx$/.test(sourceFileName); + const parser = ts + ? { syntax: 'typescript', tsx } + : { syntax: 'ecmascript', jsx: true }; + + const { code } = transformSync(source, { + sourceFileName, + inputSourceMap: inputSourceMap && JSON.stringify(inputSourceMap), + jsc: { + target: 'es2022', + parser, + }, + plugin: (m) => new ImportComponentTransformer().visitProgram(m), + }); + + return code; +} + +module.exports = importComponentLoader; diff --git a/packages/react/import-component/swc-transformer.js b/packages/react/import-component/swc-transformer.js new file mode 100644 index 0000000000..81b7ece1f0 --- /dev/null +++ b/packages/react/import-component/swc-transformer.js @@ -0,0 +1,46 @@ +const { default: Visitor } = require('@swc/core/Visitor'); +const { createAstHelper } = require('./swc-ast-helper'); + +class ImportComponentTransformer extends Visitor { + visitCallExpression(expression) { + if ( + expression.callee.type !== 'Identifier' || + expression.callee.value !== 'importComponent' + ) { + return expression; + } + + if ( + !Array.isArray(expression.arguments) || + expression.arguments.length < 1 + ) { + throw new Error( + '"importComponent" must be called with at least one parameter!' + ); + } + + const argument = expression.arguments[0].expression; + + if (argument.type !== 'ArrowFunctionExpression') { + return expression; + } + + const ast = createAstHelper(expression.span); + const importValueExpression = argument.body.arguments[0].expression; + + return ast.CallExpression( + 'importComponent', + ast.ObjectExpression({ + load: ast.ArrowFunctionExpression( + ast.CallExpression('import', importValueExpression) + ), + moduleId: ast.CallExpression( + ast.MemberExpression('require', 'resolveWeak'), + importValueExpression + ), + }) + ); + } +} + +module.exports = { ImportComponentTransformer }; diff --git a/packages/react/package.json b/packages/react/package.json index 4dc9c6e4e1..30e73912c8 100644 --- a/packages/react/package.json +++ b/packages/react/package.json @@ -26,6 +26,7 @@ "@babel/plugin-transform-flow-strip-types": "^7.9.0", "@babel/preset-react": "^7.9.4", "@pmmmwh/react-refresh-webpack-plugin": "^0.4.3", + "@swc/core": "^1.2.106", "babel-plugin-transform-react-remove-prop-types": "^0.4.24", "clone": "^2.1.2", "depd": "^2.0.0", diff --git a/yarn.lock b/yarn.lock index 6c08721501..f0670afc19 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2335,6 +2335,18 @@ outvariant "^1.2.0" strict-event-emitter "^0.2.0" +"@napi-rs/triples@^1.0.3": + version "1.0.3" + resolved "https://registry.yarnpkg.com/@napi-rs/triples/-/triples-1.0.3.tgz#76d6d0c3f4d16013c61e45dfca5ff1e6c31ae53c" + integrity sha512-jDJTpta+P4p1NZTFVLHJ/TLFVYVcOqv6l8xwOeBKNPMgY/zDYH/YH7SJbvrr/h1RcS9GzbPcLKGzpuK9cV56UA== + +"@node-rs/helper@^1.0.0": + version "1.2.1" + resolved "https://registry.yarnpkg.com/@node-rs/helper/-/helper-1.2.1.tgz#e079b05f21ff4329d82c4e1f71c0290e4ecdc70c" + integrity sha512-R5wEmm8nbuQU0YGGmYVjEc0OHtYsuXdpRG+Ut/3wZ9XAvQWyThN08bTh2cBJgoZxHQUPtvRfeQuxcAgLuiBISg== + dependencies: + "@napi-rs/triples" "^1.0.3" + "@nodelib/fs.scandir@2.1.5": version "2.1.5" resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" @@ -2608,6 +2620,86 @@ dependencies: "@sinonjs/commons" "^1.7.0" +"@swc/core-android-arm64@^1.2.106": + version "1.2.106" + resolved "https://registry.yarnpkg.com/@swc/core-android-arm64/-/core-android-arm64-1.2.106.tgz#86fb16a40d112502051252dfa29c8482b341ce36" + integrity sha512-F5T6kP3yV9S0/oXyco305QaAyE6rLNsNSdR0QI4CtACwKadiPwTOptwNIDCiTNLNgWlWLQmIRkPpxg+G4doT6Q== + +"@swc/core-darwin-arm64@^1.2.106": + version "1.2.106" + resolved "https://registry.yarnpkg.com/@swc/core-darwin-arm64/-/core-darwin-arm64-1.2.106.tgz#02a9ce94fee6d7f8a81a94233e4c455d55273fed" + integrity sha512-bgKzzYLFnc+mv2mDS/DLwzBvx5DCC9ZCKYY46b4dAnBfasr+SMHj+v/WI84HtilbjLBMUfYZ2hgYKls3CebIIQ== + +"@swc/core-darwin-x64@^1.2.106": + version "1.2.106" + resolved "https://registry.yarnpkg.com/@swc/core-darwin-x64/-/core-darwin-x64-1.2.106.tgz#72448061266e9fb44427898bd13154ec3b63ebba" + integrity sha512-I5Uhit5RqbXaMIV2+v9jL+MIQeR3lT1DqVwzxZs1bTARclAheFZQpTmg+h6QmichjCiUT74SXQb6Apc/vqYKog== + +"@swc/core-freebsd-x64@^1.2.106": + version "1.2.106" + resolved "https://registry.yarnpkg.com/@swc/core-freebsd-x64/-/core-freebsd-x64-1.2.106.tgz#070ec3ab798009ac14a18c692ede1542b5640ef1" + integrity sha512-ZSK3vgzbA2Pkpw2LgHlAkUdx4okIpdXXTbLXuc5jkZMw1KhRWpeQaDlwbrN7XVynAYjkj2qgGQ7wv1tD43vQig== + +"@swc/core-linux-arm-gnueabihf@^1.2.106": + version "1.2.106" + resolved "https://registry.yarnpkg.com/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.2.106.tgz#a94a29bfe81425c6f90a27d5977e58cb469db0a0" + integrity sha512-WZh6XV8cQ9Fh3IQNX9z87Tv68+sLtfnT51ghMQxceRhfvc5gIaYW+PCppezDDdlPJnWXhybGWNPAl5SHppWb2g== + +"@swc/core-linux-arm64-gnu@^1.2.106": + version "1.2.106" + resolved "https://registry.yarnpkg.com/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.2.106.tgz#6ec685cd37ab3655dbc8eb07a38df6d9532ac32c" + integrity sha512-OSI9VUWPsRrCbUlRQ4KdYqdwV63VYBC5ahSNq+72DXhtRwVbLSFuF7MNsnXgUSMHidxbc0No3/bPPamshqHdsQ== + +"@swc/core-linux-arm64-musl@^1.2.106": + version "1.2.106" + resolved "https://registry.yarnpkg.com/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.2.106.tgz#805841ab7bcca134a2712fb1084c09338ef61168" + integrity sha512-de8AAUOP8D2/tZIpQ399xw+pGGKlR1+l5Jmy4lW7ixarEI4xKkBSF4bS9eXtC1jckmenzrLPiK/5sSbQSf6BWQ== + +"@swc/core-linux-x64-gnu@^1.2.106": + version "1.2.106" + resolved "https://registry.yarnpkg.com/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.2.106.tgz#d403dfce5d31dafd5d87491ce80ed603545e4864" + integrity sha512-QzFC7+lBSuVBmX5tS2pdM+74voiJcGgIMJ+x9pcjUu3GkDl3ow6WC6ta2WUzlgGopCGNp6IdZaFemKRzjLr3lw== + +"@swc/core-linux-x64-musl@^1.2.106": + version "1.2.106" + resolved "https://registry.yarnpkg.com/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.2.106.tgz#0fce602e60cf1c9d9e72d33083dda18b963b3b6d" + integrity sha512-QZ1gFqNiCJefkNMihbmYc7nr5stERyjoQpWgAIN6dzrgMUzRHXHGDRl/p1qsXW2VKos+okSdLwPFEmRT94H+1A== + +"@swc/core-win32-arm64-msvc@^1.2.106": + version "1.2.106" + resolved "https://registry.yarnpkg.com/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.2.106.tgz#c0e6f5b38a6eac8a5ce438492f23c4ffc47f326f" + integrity sha512-MbuQwk+s43bfBNnAZTKnoQlfo4UPSOsy6t9F15yU4P3rVUuFtcxdZg6CpDnUqNPbojILXujp8z4SSigRYh5cgg== + +"@swc/core-win32-ia32-msvc@^1.2.106": + version "1.2.106" + resolved "https://registry.yarnpkg.com/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.2.106.tgz#5cf4a824a5bc3cfa6346733a3407e423c1920020" + integrity sha512-BFxWpcPxsG2LLQZ+8K8ma45rbTckjpPbnvOOhybQ0hEhLgoVzMVPp3RIUGmC+RMZe6DkGSaEQf/Rjn2cbMdQhw== + +"@swc/core-win32-x64-msvc@^1.2.106": + version "1.2.106" + resolved "https://registry.yarnpkg.com/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.2.106.tgz#237d699d25944538fda57dd879478f2cc7835827" + integrity sha512-Emn5akqApGXzPsA7ntSXEohL0AH0WjQMHy6mT3MS9Yil42yTJ96dJGf68ejKVptxwg7Iz798mT+J9r1JbAFBgg== + +"@swc/core@^1.2.106": + version "1.2.106" + resolved "https://registry.yarnpkg.com/@swc/core/-/core-1.2.106.tgz#d1ae8d5745b6b37fcc5c076e433eb31312c81372" + integrity sha512-9uw8gqU+lsk7KROAcSNhsrnBgNiC5H4MIaps5LlnnEevJmKu/o1ws22tXc2qjJg+F4/V1ynUbh8E0rYlmo1XGw== + dependencies: + "@node-rs/helper" "^1.0.0" + optionalDependencies: + "@swc/core-android-arm64" "^1.2.106" + "@swc/core-darwin-arm64" "^1.2.106" + "@swc/core-darwin-x64" "^1.2.106" + "@swc/core-freebsd-x64" "^1.2.106" + "@swc/core-linux-arm-gnueabihf" "^1.2.106" + "@swc/core-linux-arm64-gnu" "^1.2.106" + "@swc/core-linux-arm64-musl" "^1.2.106" + "@swc/core-linux-x64-gnu" "^1.2.106" + "@swc/core-linux-x64-musl" "^1.2.106" + "@swc/core-win32-arm64-msvc" "^1.2.106" + "@swc/core-win32-ia32-msvc" "^1.2.106" + "@swc/core-win32-x64-msvc" "^1.2.106" + "@testing-library/dom@^8.0.0": version "8.1.1" resolved "https://registry.yarnpkg.com/@testing-library/dom/-/dom-8.1.1.tgz#44308211c92cc5c82190e940e101d452b684f62e"