第2部分:使用 Nx.js 建立微前端的 Nx Monorepo
Nx.js 是一个强大的单仓库管理工具,用于在开发过程中创建和运行项目。在 Nx.js 管理的单仓库中,所有依赖项都位于同一根 node_modules 中,而项目则以并行方式列出。当存在一系列小型项目具有相似技术栈和共享依赖项时,这种方式特别有优势。
Nx.js 的另一个亮点是它是开源的,你可以构建自己的扩展,甚至在必要时更改一些核心功能。感谢开发者社区,有许多用于生成、运行和部署项目的 Nx.js 扩展和插件。
让我们开始吧。要使用 Nx.js 创建一个 Nx Monorepo,请确保已安装 Node.js,并运行以下命令:
sql
npx create-nx-workspace@latest
命令行中提供了清晰的工具,你可以根据你的业务情况创建工作空间。在我的情况下,我只创建了一个空工作空间,稍后再创建项目。我将工作空间命名为 "harper-ws"。
因为我们的工作空间是为在 Single SPA 中托管的微前端项目设计的,所以我们只需在工作空间中添加 @nx/react
作为我们的生成器:
sql
yarn add @nx/react -W -D
请确保在命令中使用 -W,它将在同一 node_modules 中安装你的依赖项。
现在我们可以创建我们的第一个项目了:
scss
npx nx g @nx/react:app
或者,如果你将 Nx 安装为全局模块:
shell
npm install -g nx
nx g @nx/react:app
选择一个项目名称,例如 "dashboard"。在创建了 React 应用之后,我们需要进行一些更改,以便将其作为 Single SPA 单应用程序进行托管。
首先,让我们创建一个生命周期文件,文件名的格式必须是 <math xmlns="http://www.w3.org/1998/Math/MathML"> o r g N a m e − {orgName}- </math>orgName−{projectName}。例如,如果组织名称是 "QuickBot",那么文件名应该是 "QuickBot-dashboard.js",在文件中:
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 进行一些更改,以便将应用程序设为懒加载:
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:
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 文件:
json
{
"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 的示例代码:
tsx
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 配置运行,例如:
shell
npx webpack serve --config extra-webpack.config.js --port 8081
因此,我在根 package.json 中添加了一个脚本:
json
{
"scripts": {
"dashboard:serve": "npx webpack serve --config ./dashboard/extra-webpack.config.js -- port 8081"
}
}
现在,运行 yarn dashboard:serve ,并在浏览器中打开 http://localhost:8081。页面上的链接对应于你想要在 "root-config" 项目中托管的 JavaScript 文件。