diff --git a/common/changes/@microsoft/rush/rush-sdk-webpack_2022-02-05-03-03.json b/common/changes/@microsoft/rush/rush-sdk-webpack_2022-02-05-03-03.json new file mode 100644 index 00000000000..ded1596f677 --- /dev/null +++ b/common/changes/@microsoft/rush/rush-sdk-webpack_2022-02-05-03-03.json @@ -0,0 +1,10 @@ +{ + "changes": [ + { + "packageName": "@microsoft/rush", + "comment": "Add support for rush-sdk to be bundled with Webpack.", + "type": "none" + } + ], + "packageName": "@microsoft/rush" +} \ No newline at end of file diff --git a/common/config/rush/pnpm-lock.yaml b/common/config/rush/pnpm-lock.yaml index 464eba84b9e..7a8ced6712c 100644 --- a/common/config/rush/pnpm-lock.yaml +++ b/common/config/rush/pnpm-lock.yaml @@ -1634,9 +1634,9 @@ importers: '@rushstack/heft-node-rig': workspace:* '@rushstack/node-core-library': workspace:* '@types/heft-jest': 1.0.1 - '@types/node': 12.20.24 '@types/node-fetch': 1.6.9 '@types/semver': 7.3.5 + '@types/webpack-env': 1.13.0 tapable: 2.2.1 dependencies: '@rushstack/node-core-library': link:../node-core-library @@ -1648,8 +1648,8 @@ importers: '@rushstack/heft': link:../../apps/heft '@rushstack/heft-node-rig': link:../../rigs/heft-node-rig '@types/heft-jest': 1.0.1 - '@types/node': 12.20.24 '@types/semver': 7.3.5 + '@types/webpack-env': 1.13.0 ../../libraries/rushell: specifiers: diff --git a/libraries/rush-sdk/config/typescript.json b/libraries/rush-sdk/config/typescript.json new file mode 100644 index 00000000000..9da485f84fb --- /dev/null +++ b/libraries/rush-sdk/config/typescript.json @@ -0,0 +1,9 @@ +/** + * Configures the TypeScript plugin for Heft. This plugin also manages linting. + */ +{ + "$schema": "https://developer.microsoft.com/json-schemas/heft/typescript.schema.json", + "extends": "@rushstack/heft-node-rig/profiles/default/config/typescript.json", + + "emitMjsExtensionForESModule": true +} diff --git a/libraries/rush-sdk/package.json b/libraries/rush-sdk/package.json index 42826ce4100..f6631d5841a 100644 --- a/libraries/rush-sdk/package.json +++ b/libraries/rush-sdk/package.json @@ -9,6 +9,7 @@ }, "homepage": "https://rushjs.io", "main": "lib/index.js", + "module": "lib/index.mjs", "typings": "dist/rush-lib.d.ts", "scripts": { "build": "heft build --clean", @@ -27,7 +28,7 @@ "@rushstack/heft": "workspace:*", "@rushstack/heft-node-rig": "workspace:*", "@types/heft-jest": "1.0.1", - "@types/node": "12.20.24", - "@types/semver": "7.3.5" + "@types/semver": "7.3.5", + "@types/webpack-env": "1.13.0" } } diff --git a/libraries/rush-sdk/src/index.ts b/libraries/rush-sdk/src/index.ts index 54501826052..e619eca098d 100644 --- a/libraries/rush-sdk/src/index.ts +++ b/libraries/rush-sdk/src/index.ts @@ -31,6 +31,18 @@ declare const global: NodeJS.Global & ___rush___rushLibModuleFromInstallAndRunRush?: RushLibModuleType; }; +function _require(moduleName: string): TResult { + if (typeof __non_webpack_require__ === 'function') { + // If this library has been bundled with Webpack, we need to call the real `require` function + // that doesn't get turned into a `__webpack_require__` statement. + // `__non_webpack_require__` is a Webpack macro that gets turned into a `require` statement + // during bundling. + return __non_webpack_require__(moduleName); + } else { + return require(moduleName); + } +} + // SCENARIO 1: Rush's PluginManager has initialized "rush-sdk" with Rush's own instance of rush-lib. // The Rush host process will assign "global.___rush___rushLibModule" before loading the plugin. let rushLibModule: RushLibModuleType | undefined = @@ -40,13 +52,13 @@ let errorMessage: string = ''; // SCENARIO 2: The project importing "rush-sdk" has installed its own instance of "rush-lib" // as a package.json dependency. For example, this is used by the Jest tests for Rush plugins. if (rushLibModule === undefined) { - const importingPath: string | undefined = module?.parent?.filename; - if (importingPath !== undefined) { + const importingPath: string | null | undefined = module?.parent?.filename; + if (importingPath) { const callerPackageFolder: string | undefined = PackageJsonLookup.instance.tryGetPackageFolderFor(importingPath); if (callerPackageFolder !== undefined) { - const callerPackageJson: IPackageJson = require(path.join(callerPackageFolder, 'package.json')); + const callerPackageJson: IPackageJson = _require(path.join(callerPackageFolder, 'package.json')); // Does the caller properly declare a dependency on rush-lib? if ( @@ -123,7 +135,9 @@ if (rushLibModule === undefined) { } // Retry to load "rush-lib" after install-run-rush run - terminal.writeVerboseLine(`Trying to load ${RUSH_LIB_NAME} installed by install-run-rush a second time`); + terminal.writeVerboseLine( + `Trying to load ${RUSH_LIB_NAME} installed by install-run-rush a second time` + ); rushLibModule = requireRushLibUnderFolderPath(installRunNodeModuleFolder); } catch (e) { console.error(`${installAndRunRushStderrContent}`); @@ -176,7 +190,7 @@ function requireRushLibUnderFolderPath(folderPath: string): RushLibModuleType { baseFolderPath: folderPath }); - return require(rushLibModulePath); + return _require(rushLibModulePath); } /** diff --git a/libraries/rush-sdk/src/test/script.test.ts b/libraries/rush-sdk/src/test/script.test.ts index a367dce25c4..e795a0abedc 100644 --- a/libraries/rush-sdk/src/test/script.test.ts +++ b/libraries/rush-sdk/src/test/script.test.ts @@ -15,16 +15,16 @@ describe('used in script', () => { [ '-e', ` -const { Import } = require("${coreLibPath}"); +const { Import } = require(${JSON.stringify(coreLibPath)}); const originalResolveModule = Import.resolveModule; const mockResolveModule = (options) => { if (options.baseFolderPath.includes('install-run') && options.modulePath === '@microsoft/rush-lib') { - return "${mockRushLibPath}"; + return ${JSON.stringify(mockRushLibPath)}; } return originalResolveModule(options); } Import.resolveModule = mockResolveModule; -console.log(require("${rushSdkPath}")); +console.log(require(${JSON.stringify(rushSdkPath)})); ` ], { diff --git a/libraries/rush-sdk/tsconfig.json b/libraries/rush-sdk/tsconfig.json index 22f94ca28b5..ab74a420295 100644 --- a/libraries/rush-sdk/tsconfig.json +++ b/libraries/rush-sdk/tsconfig.json @@ -1,6 +1,9 @@ { "extends": "./node_modules/@rushstack/heft-node-rig/profiles/default/tsconfig-base.json", "compilerOptions": { - "types": ["heft-jest", "node"] + "types": [ + "heft-jest", + "webpack-env" // Use webpack-env here instead of node so we have __non_webpack_require__ + ] } }