UNPKG

@nx/react

Version:

The React plugin for Nx contains executors and generators for managing React applications and libraries within an Nx workspace. It provides: - Integration with libraries such as Jest, Vitest, Playwright, Cypress, and Storybook. - Generators for applica

154 lines (153 loc) • 8.41 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.addModuleFederationFiles = addModuleFederationFiles; exports.remoteGenerator = remoteGenerator; const path_1 = require("path"); const devkit_1 = require("@nx/devkit"); const normalize_options_1 = require("../application/lib/normalize-options"); const application_1 = require("../application/application"); const update_host_with_remote_1 = require("./lib/update-host-with-remote"); const update_module_federation_project_1 = require("../../rules/update-module-federation-project"); const setup_ssr_1 = require("../setup-ssr/setup-ssr"); const setup_ssr_for_remote_1 = require("./lib/setup-ssr-for-remote"); const setup_tspath_for_remote_1 = require("./lib/setup-tspath-for-remote"); const add_remote_to_dynamic_host_1 = require("./lib/add-remote-to-dynamic-host"); const add_mf_env_to_inputs_1 = require("../../utils/add-mf-env-to-inputs"); const maybe_js_1 = require("../../utils/maybe-js"); const js_1 = require("@nx/js"); const versions_1 = require("../../utils/versions"); const project_name_and_root_utils_1 = require("@nx/devkit/src/generators/project-name-and-root-utils"); const create_application_files_1 = require("../application/lib/create-application-files"); function addModuleFederationFiles(host, options) { const templateVariables = options.bundler === 'rspack' ? { ...(0, create_application_files_1.getDefaultTemplateVariables)(host, options), rspackPluginOptions: { ...(0, create_application_files_1.createNxRspackPluginOptions)(options, (0, devkit_1.offsetFromRoot)(options.appProjectRoot), false), mainServer: `./server.ts`, }, } : { ...(0, devkit_1.names)(options.projectName), ...options, tmpl: '', }; (0, devkit_1.generateFiles)(host, (0, path_1.join)(__dirname, `./files/${options.js ? options.bundler === 'rspack' ? 'rspack-common' : 'common' : 'common-ts'}`), options.appProjectRoot, templateVariables); const pathToModuleFederationFiles = options.typescriptConfiguration ? `${options.bundler === 'rspack' ? 'rspack-' : 'webpack-'}module-federation-ts` : `${options.bundler === 'rspack' ? 'rspack-' : 'webpack-'}module-federation`; (0, devkit_1.generateFiles)(host, (0, path_1.join)(__dirname, `./files/${pathToModuleFederationFiles}`), options.appProjectRoot, templateVariables); if (options.typescriptConfiguration) { const pathToBundlerConfig = (0, devkit_1.joinPathFragments)(options.appProjectRoot, options.bundler === 'rspack' ? 'rspack.config.js' : 'webpack.config.js'); const pathToWebpackProdConfig = (0, devkit_1.joinPathFragments)(options.appProjectRoot, options.bundler === 'rspack' ? 'rspack.config.prod.js' : 'webpack.config.prod.js'); if (host.exists(pathToBundlerConfig)) { host.delete(pathToBundlerConfig); } if (host.exists(pathToWebpackProdConfig)) { host.delete(pathToWebpackProdConfig); } } } async function remoteGenerator(host, schema) { const tasks = []; const options = { ...(await (0, normalize_options_1.normalizeOptions)(host, { ...schema, useProjectJson: true, })), // when js is set to true, we want to use the js configuration js: schema.js ?? false, typescriptConfiguration: schema.js ? false : schema.typescriptConfiguration ?? true, dynamic: schema.dynamic ?? false, // TODO(colum): remove when Webpack MF works with Crystal addPlugin: !schema.bundler || schema.bundler === 'rspack' ? true : false, bundler: schema.bundler ?? 'rspack', }; if (options.dynamic) { // Dynamic remotes generate with library { type: 'var' } by default. // We need to ensure that the remote name is a valid variable name. const isValidRemote = (0, js_1.isValidVariable)(options.projectName); if (!isValidRemote.isValid) { throw new Error(`Invalid remote name provided: ${options.projectName}. ${isValidRemote.message}`); } } await (0, project_name_and_root_utils_1.ensureRootProjectName)(options, 'application'); const REMOTE_NAME_REGEX = '^[a-zA-Z_$][a-zA-Z_$0-9]*$'; const remoteNameRegex = new RegExp(REMOTE_NAME_REGEX); if (!remoteNameRegex.test(options.projectName)) { throw new Error((0, devkit_1.stripIndents) `Invalid remote name: ${options.projectName}. Remote project names must: - Start with a letter, dollar sign ($) or underscore (_) - Followed by any valid character (letters, digits, underscores, or dollar signs) The regular expression used is ${REMOTE_NAME_REGEX}.`); } const initAppTask = await (0, application_1.default)(host, { ...options, name: options.projectName, skipFormat: true, useProjectJson: true, }); tasks.push(initAppTask); if (options.host) { (0, update_host_with_remote_1.updateHostWithRemote)(host, options.host, options.projectName); } // Module federation requires bootstrap code to be dynamically imported. // Renaming original entry file so we can use `import(./bootstrap)` in // new entry file. host.rename((0, path_1.join)(options.appProjectRoot, (0, maybe_js_1.maybeJs)({ js: options.js, useJsx: options.bundler === 'rspack' }, 'src/main.tsx')), (0, path_1.join)(options.appProjectRoot, (0, maybe_js_1.maybeJs)({ js: options.js, useJsx: options.bundler === 'rspack' }, 'src/bootstrap.tsx'))); addModuleFederationFiles(host, options); (0, update_module_federation_project_1.updateModuleFederationProject)(host, options); (0, setup_tspath_for_remote_1.setupTspathForRemote)(host, options); if (options.ssr) { if (options.bundler !== 'rspack') { const setupSsrTask = await (0, setup_ssr_1.default)(host, { project: options.projectName, serverPort: options.devServerPort, skipFormat: true, bundler: options.bundler, }); tasks.push(setupSsrTask); } const setupSsrForRemoteTask = await (0, setup_ssr_for_remote_1.setupSsrForRemote)(host, options, options.projectName); tasks.push(setupSsrForRemoteTask); const projectConfig = (0, devkit_1.readProjectConfiguration)(host, options.projectName); if (options.bundler !== 'rspack') { projectConfig.targets.server.options.webpackConfig = (0, devkit_1.joinPathFragments)(projectConfig.root, `webpack.server.config.${options.typescriptConfiguration ? 'ts' : 'js'}`); (0, devkit_1.updateProjectConfiguration)(host, options.projectName, projectConfig); } } if (!options.setParserOptionsProject) { host.delete((0, devkit_1.joinPathFragments)(options.appProjectRoot, 'tsconfig.lint.json')); } if (options.host && options.bundler === 'rspack') { const projectConfig = (0, devkit_1.readProjectConfiguration)(host, options.projectName); projectConfig.targets.serve ??= {}; projectConfig.targets.serve.dependsOn ??= []; projectConfig.targets.serve.dependsOn.push(`${options.host}:serve`); (0, devkit_1.updateProjectConfiguration)(host, options.projectName, projectConfig); } if (options.host && options.dynamic) { const hostConfig = (0, devkit_1.readProjectConfiguration)(host, schema.host); const pathToMFManifest = (0, devkit_1.joinPathFragments)(hostConfig.sourceRoot, 'assets/module-federation.manifest.json'); (0, add_remote_to_dynamic_host_1.addRemoteToDynamicHost)(host, options.projectName, options.devServerPort, pathToMFManifest); } (0, add_mf_env_to_inputs_1.addMfEnvToTargetDefaultInputs)(host, options.bundler); const installTask = (0, devkit_1.addDependenciesToPackageJson)(host, {}, { '@module-federation/enhanced': versions_1.moduleFederationEnhancedVersion, '@nx/web': versions_1.nxVersion, '@nx/module-federation': versions_1.nxVersion, }); tasks.push(installTask); if (!options.skipFormat) { await (0, devkit_1.formatFiles)(host); } return (0, devkit_1.runTasksInSerial)(...tasks); } exports.default = remoteGenerator;