第2部分:运用 Nx.js 树立微前端的 Nx Monorepo

Nx.js 是一个强壮的单库房办理东西,用于在开发过程中创立和运转项目。在 Nx.js 办理的单库房中,所有依靠项都坐落同一根 node_modules 中,而项目则以并行方法列出。当存在一系列小型项目具有相似技术栈和同享依靠项时,这种方法特别有优势。

Nx.js 的另一个亮点是它是开源的,你能够构建自己的扩展,甚至在必要时更改一些核心功用。感谢开发者社区,有许多用于生成、运转和部署项目的 Nx.js 扩展和插件。

让咱们开端吧。要运用 Nx.js 创立一个 Nx Monorepo,请保证已装置 Node.js,并运转以下指令:

npx create-nx-workspace@latest

指令行中供给了明晰的东西,你能够根据你的业务状况创立作业空间。在我的状况下,我只创立了一个空作业空间,稍后再创立项目。我将作业空间命名为 “harper-ws”。

由于咱们的作业空间是为在 Single SPA 中保管的微前端项目设计的,所以咱们只需在作业空间中添加 @nx/react 作为咱们的生成器:

yarn add @nx/react -W -D

请保证在指令中运用 -W,它将在同一 node_modules 中装置你的依靠项。

现在咱们能够创立咱们的第一个项目了:

npx nx g @nx/react:app

或者,假如你将 Nx 装置为全局模块:

npm install -g nx
nx g @nx/react:app

挑选一个项目名称,例如 “dashboard”。在创立了 React 使用之后,咱们需求进行一些更改,以便将其作为 Single SPA 单使用程序进行保管。

首先,让咱们创立一个生命周期文件,文件名的格局有必要是 orgName−{orgName}-{projectName}。例如,假如安排名称是 “QuickBot”,那么文件名应该是 “QuickBot-dashboard.js”,在文件中:

import App from './app/app.tsx';
const lc = singleSpaReact({
    React,
    ReactDOMClient,
    rootComponent: App,
    renderType: "createRoot",
    errorBoundary(err, _info, _props) {
        return null
    }
});
export const { bootstrap, mount, unmount } = lc;
export default lc

也别忘了对 App.tsx 进行一些更改,以便将使用程序设为懒加载:

import styles from './app.module.scss';
import React, { Suspense } from 'react';
import { Home } from '@src/page/home/index';
import { BrowserRouter } from 'react-router-dom';
export function App() {
  return (
    <Suspense fallback={<div>Loading...</div>}>
      <BrowserRouter>
          <Home />
      </BrowserRouter>
    </Suspense>
  );
}
export default React.memo(App);

并且不要忘记 main.tsx:

import React, { StrictMode } from 'react';
import * as ReactDOM from 'react-dom/client';
const LazyApp = React.lazy(() => import('./app/app'));
const root = ReactDOM.createRoot(
  document.getElementById('root') as HTMLElement
);
root.render(
  <StrictMode>
    <LazyApp />
  </StrictMode>
);

下一个需求更新的文件是 tsconfig.json 文件,这是我的 tsconfig 文件:

{
  "compilerOptions": {
    "jsx": "react-jsx",
    "allowJs": false,
    "esModuleInterop": false,
    "allowSyntheticDefaultImports": true,
    "strict": true,
    "baseUrl": "./",
    "paths": {
      "@app/*": ["src/app/*"],
      "@env/*": ["src/environments/*"],
      "@src/*": ["src/*"],
      "@components/*": ["src/components/*"],
      "@assets/*": ["src/assets/*"],
      "@store/*": ["src/store/*"],
    },
  },
  "files": [],
  // 有时你或许需求一个 declaration.d.ts 文件,然后将其添加到 include 中
  "include": [],
  "references": [
    {
      "path": "./tsconfig.app.json"
    },
    {
      "path": "./tsconfig.spec.json"
    }
  ],
  "extends": "../tsconfig.base.json"
}

接下来咱们需求做的必要的工作是编写咱们的 extra-webpack.config.js。不建议更改自动生成的 webpack.config.js 文件。以下是 extra-webpack.config.js 的示例代码:

const { merge } = require('webpack-merge');
const singleSpaDefaults = require('webpack-config-single-spa-react');
const ModuleFederationPlugin = require('webpack/lib/container/ModuleFederationPlugin');
const path = require('path');
module.exports = (webpackConfigEnv, argv) => {
  const defaultConfig = singleSpaDefaults({
    orgName: 'QuickBot', // 保证你的 orgName 正确
    projectName: 'dashboard', // 还有 dashboard
    webpackConfigEnv,
    argv,
  });
  return merge(defaultConfig, {
    output: {
      path: path.resolve(__dirname, '..', 'singlespa-dist', 'dashboard'),
    },
    resolve: {
      extensions: ['.js', '.ts', '.tsx', '.jsx'],
      alias: {
        fs: path.resolve(__dirname, 'node_modules/browserify-fs'),
        '@src': path.resolve(__dirname,'src'),
        '@components': path.resolve(__dirname,'src', 'components'),
        '@app': path.resolve(__dirname,'src', 'app'),
        '@env': path.resolve(__dirname,'src', 'environments'),
        '@assets': path.resolve(__dirname, 'assets'),
        '@store': path.resolve(__dirname,'src','store'),
      },
    },
    plugins: [
    ],
    module: {
      rules: [
        {
          test: /.s[ac]ss$/i,
          use: [
            'style-loader',
            'css-loader',
            {
              loader: 'sass-loader',
              options: {
                implementation: require('sass'),
                sassOptions: {
                  fiber: false,
                },
              },
            },
          ],
        },
        { parser: { System: false } },
        {
          test: /.js|.ts|.tsx|.jsx$/,
          exclude: /(node_modules|bower_components)/,
          use: {
            loader: 'babel-loader',
          },
        },
      ],
    },
  });
};

在开发使用程序时,你能够运用 “nx serve” 指令,但要作为单一的 Single SPA 微前端运转,你需求运用咱们自定义的 webpack 配置运转,例如:

npx webpack serve --config extra-webpack.config.js --port 8081

因而,我在根 package.json 中添加了一个脚本:

{
	 "scripts": {
	   "dashboard:serve": "npx webpack serve --config ./dashboard/extra-webpack.config.js --   port 8081"
	 }
}

现在,运转 yarn dashboard:serve,并在浏览器中翻开 http://localhost:8081。页面上的链接对应于你想要在 “root-config” 项目中保管的 JavaScript 文件。