-
Help, using webpack to customize the loader react router config loader will result in an error, as shown in the following figure. rsbuild.config.mjs import { defineConfig } from '@rsbuild/core';
import { pluginReact } from '@rsbuild/plugin-react';
import { pluginLess } from '@rsbuild/plugin-less';
import { pluginBabel } from '@rsbuild/plugin-babel';
import path from 'node:path';
export default defineConfig({
plugins: [
pluginReact(),
pluginLess(),
pluginBabel(),
],
html: {
mountId: 'root',
template: path.resolve(__dirname, './template/index.html'),
},
server: {
port: 8804,
},
source: {
alias: {
'@': path.resolve(__dirname, '../src'),
},
},
tools: {
rspack: (config, { addRules }) => {
addRules({
test: /router\.config\.js/,
loader: require.resolve('./loaders/react-router-config-loader'),
});
},
},
}); react-router-config-loader.js /**
* 根据path设置webpackChunkName
* @param {*} route
*/
function handleChunkName(route) {
if (route.path === '/') {
const path = route.component.split('/');
return path[path.length - 1];
}
// FIXED: * 模糊匹配windows无法解析
if (route.path === '*') {
return 'fuzzyMatching'
}
// FIXED: 动态传参路由异步加载报错
return route.path.replace(/^\//, '').split('/').filter(path => !path.includes(':')).join('-');
}
/**
* 处理路由数据为string(处理国际化模板)
* @param {Object} route 路由信息
* @return string;
*/
function getRouteString(route) {
const REG1 = /intl\.get\([\'\"\\]([^\)]*)[\'\"\\]\)\.d\([\'\"\\]([^\)]*)[\'\"\\]\)/g;
const REG2 = /"intl\.get\([\'\"\\]([^\)]*)[\'\"\\]\)\.d\([\'\"\\]([^\)]*)[\'\"\\]\)"/g;
let str = JSON.stringify(route);
const match1 = str.match(REG1);
const match2 = str.match(REG2);
if (!match2) {
return str;
}
match2.forEach((item, index) => {
str = str.replace(item, match1[index].replace(/\\/g, ''))
})
return str;
}
/**
* 处理route
* @param {*} route
*/
function createRoute(route) {
const isRouter = route.isRouter === undefined ? true : route.isRouter
const routes = route.routes || [];
const code = route.code || '';
if (route.from && route.to) {
return `<Redirect from="${route.from}" to="${route.to}" />`;
}
let Route = route.cache ? 'CacheRoute' : 'Route';
if (route.cache) {
}
return isRouter ? `
<${Route}
className='cache-route-wrapper'
cacheKey="${route.path}"
key="${route.path}"
path="${route.path}"
exact={${route.exact}}
render={props => {
const hasAuth = '${code}' ? getAuth('${route.code}') : true;
if(!hasAuth) {
return <NoAuth />;
}
const finalCom = ${route.dynamic === false || process.env.useMultipleTheme === 'true' ? route.component : route.dynamicComponent};
const RouteComponent = useCache ? dynamicComponentMap['${route.path}'] || finalCom : finalCom;
if(useCache && !dynamicComponentMap['${route.path}']) {
dynamicComponentMap['${route.path}'] = RouteComponent;
}
const JsxRouteCom = <RouteComponent route={${getRouteString(route)}} {...props} {...res}>
${routes.length > 0 ? createRoutes(routes) : ''}
</RouteComponent>
if(hocRouteWrapper) {
const newStroe = ${concatStore(route.stores || {})}
return hocRouteWrapper(JsxRouteCom, newStroe)
}
return JsxRouteCom
}}
{...${JSON.stringify(route.resRouteConfig || {})}}
/>
` : ``;
}
function createRoutes(routes) {
const RouteComponents = routes.reduce((components, route) => {
return components += createRoute(route);
}, '');
return `
<Switch>
${RouteComponents}
</Switch>
`;
}
/**
* 处理store
*/
function concatStore(stores = {}) {
let storeStr = '{';
for (const [key, store] of Object.entries(stores)) {
storeStr += `${key}: require('${store}').default,`
}
storeStr += '}';
return storeStr;
}
/**
* 按需引入路由 格式化
* @param {*} routerConfig
*/
function formateConfigData(routerConfig) {
if (!routerConfig) {
return [];
}
return routerConfig.map(item => {
const common = (item.component ? {
...item,
dynamicComponent: `loadable(() => import(/* webpackChunkName: "${handleChunkName(item)}" */'${item.component}'), {
fallback: <Loading />
})`,
component: `require('${item.component}').default`,
} : item)
if (item.routes) {
return {
...common,
routes: formateConfigData(item.routes)
}
}
return common;
})
}
const Module = require("module");
function exec(code, filename) {
const module = new Module(filename, this);
module.paths = Module._nodeModulePaths(this.context);
module.filename = filename;
module._compile(code, filename);
return module.exports;
}
/**
* 判断是否需要国际化intl
* @param {*} content router.config内容
* @returns 是否引入国际化 intl
*/
function judgeImportIntl(content) {
const REG = /intl\.get\([\'\"]([^\)]*)[\'\"]\)\.d\([\'\"]([^\)]*)[\'\"]\)/g;
if (typeof content === "string" && REG.test(content)) {
return true;
}
return false;
}
module.exports = function (content) {
const isUseIntl = judgeImportIntl(content);
const routerConfig = exec.call(this, content, this.resource);
const NoAuth = routerConfig.noAuthShow ? `require('${routerConfig.noAuthShow}').default` : '() => <div>403 无权限</div>'
const Loading = routerConfig.loadingComponent ? `require('${routerConfig.loadingComponent}').default` : '() => <div>Loading...</div>'
const hocRouteWrapper = routerConfig.hocRouteWrapper ? `require('${routerConfig.hocRouteWrapper}').default` : 'null'
const routerType = process.env.routerType === 'browser' ? 'BrowserRouter' : 'HashRouter';
return `/* eslint-disable */
import React from 'react';
import { BrowserRouter, HashRouter, Redirect, Route } from 'react-router-dom';
import CacheRoute, { CacheSwitch as Switch } from 'react-router-cache-route'
import loadable from "@loadable/component";
${isUseIntl ? "import { intl } from '@chaoswise/intl';" : ""}
const Loading = ${Loading};
const NoAuth = ${NoAuth};
const hocRouteWrapper = ${hocRouteWrapper};
const dynamicComponentMap = {};
export const routerConfig = ${JSON.stringify(formateConfigData(routerConfig.routes))};
export default ({
getAuth,
basename,
routerType,
useCache = true,
...res
}) => {
let Router = ${routerType};
if(routerType && ['hash', 'browser'].includes(routerType)) {
Router = routerType === 'browser' ? BrowserRouter : HashRouter
}
return (
<Router
basename={basename || ''}
{
...res
}
>
${createRoutes(formateConfigData(routerConfig.routes))}
</Router>
)
}
`;
}; |
Beta Was this translation helpful? Give feedback.
Answered by
9aoy
Oct 18, 2024
Replies: 1 comment 1 reply
-
The |
Beta Was this translation helpful? Give feedback.
1 reply
Answer selected by
chenjiahan
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
The
addRules(...)
method will prepend rules to Rspack rule list. In your scenario, I think you should useconfig.module.rules.push(...)
https://rsbuild.dev/config/tools/rspack#addrules