ssr-plugin-react 6.2.11 → 6.2.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +2995 -0
- package/cjs/config/base.js +12 -5
- package/cjs/config/client.js +10 -1
- package/cjs/entry/client-entry.js +1 -4
- package/cjs/entry/server-entry.js +5 -11
- package/cjs/tools/vite.js +6 -6
- package/esm/config/base.js +12 -5
- package/esm/config/client.js +10 -1
- package/esm/entry/client-entry.js +1 -4
- package/esm/entry/server-entry.js +6 -12
- package/esm/tools/vite.js +7 -7
- package/package.json +4 -2
- package/src/config/base.ts +13 -5
- package/src/config/client.ts +11 -1
- package/src/entry/client-entry.tsx +0 -4
- package/src/entry/server-entry.tsx +6 -13
- package/src/tools/vite.ts +7 -7
package/cjs/config/base.js
CHANGED
|
@@ -7,9 +7,9 @@ const webpack = require("webpack");
|
|
|
7
7
|
const MiniCssExtractPlugin = require((0, ssr_server_utils_1.loadModuleFromFramework)('mini-css-extract-plugin'));
|
|
8
8
|
const WebpackBar = require('webpackbar');
|
|
9
9
|
const loadModule = ssr_server_utils_1.loadModuleFromFramework;
|
|
10
|
-
const addBabelLoader = (chain, envOptions) => {
|
|
10
|
+
const addBabelLoader = (chain, envOptions, isServer) => {
|
|
11
11
|
var _a, _b;
|
|
12
|
-
const { babelOptions } = (0, ssr_server_utils_1.loadConfig)();
|
|
12
|
+
const { babelOptions, isDev } = (0, ssr_server_utils_1.loadConfig)();
|
|
13
13
|
chain.use('babel-loader')
|
|
14
14
|
.loader(loadModule('babel-loader'))
|
|
15
15
|
.options({
|
|
@@ -41,7 +41,7 @@ const addBabelLoader = (chain, envOptions) => {
|
|
|
41
41
|
[loadModule('@babel/plugin-proposal-private-methods'), { loose: true }],
|
|
42
42
|
[loadModule('@babel/plugin-proposal-private-property-in-object'), { loose: true }],
|
|
43
43
|
...(_b = babelOptions === null || babelOptions === void 0 ? void 0 : babelOptions.plugins) !== null && _b !== void 0 ? _b : []
|
|
44
|
-
]
|
|
44
|
+
].concat((!isServer && isDev) ? loadModule('react-refresh/babel') : [])
|
|
45
45
|
})
|
|
46
46
|
.end();
|
|
47
47
|
};
|
|
@@ -79,6 +79,13 @@ const getBaseConfig = (chain, isServer) => {
|
|
|
79
79
|
.exclude
|
|
80
80
|
.add(/node_modules|core-js/)
|
|
81
81
|
.end();
|
|
82
|
+
chain.module
|
|
83
|
+
.rule('mjs')
|
|
84
|
+
.test(/\.mjs/)
|
|
85
|
+
.include
|
|
86
|
+
.add(/node_modules/).end()
|
|
87
|
+
.type('javascript/auto')
|
|
88
|
+
.end();
|
|
82
89
|
const module = chain.module
|
|
83
90
|
.rule('compileBabelForExtraModule')
|
|
84
91
|
.test(/\.(js|mjs|jsx|ts|tsx)$/)
|
|
@@ -91,8 +98,8 @@ const getBaseConfig = (chain, isServer) => {
|
|
|
91
98
|
else {
|
|
92
99
|
babelForExtraModule = module.end().exclude.add(/core-js/).end();
|
|
93
100
|
}
|
|
94
|
-
addBabelLoader(babelModule, envOptions);
|
|
95
|
-
addBabelLoader(babelForExtraModule, envOptions);
|
|
101
|
+
addBabelLoader(babelModule, envOptions, isServer);
|
|
102
|
+
addBabelLoader(babelForExtraModule, envOptions, isServer);
|
|
96
103
|
(0, ssr_server_utils_1.setStyle)(chain, /\.css$/, {
|
|
97
104
|
rule: 'css',
|
|
98
105
|
isServer,
|
package/cjs/config/client.js
CHANGED
|
@@ -8,11 +8,12 @@ const base_1 = require("./base");
|
|
|
8
8
|
const ModuleNotFoundPlugin = require('react-dev-utils/ModuleNotFoundPlugin');
|
|
9
9
|
const safePostCssParser = require('postcss-safe-parser');
|
|
10
10
|
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
|
|
11
|
+
const ReactRefreshWebpackPlugin = require('@pmmmwh/react-refresh-webpack-plugin');
|
|
11
12
|
const generateAnalysis = Boolean(process.env.GENERATE_ANALYSIS);
|
|
12
13
|
const loadModule = ssr_server_utils_1.loadModuleFromFramework;
|
|
13
14
|
let asyncChunkMap = {};
|
|
14
15
|
const getClientWebpack = (chain) => {
|
|
15
|
-
const { isDev, chunkName, getOutput, cwd, useHash, chainClientConfig } = (0, ssr_server_utils_1.loadConfig)();
|
|
16
|
+
const { isDev, chunkName, getOutput, cwd, useHash, chainClientConfig, host, fePort } = (0, ssr_server_utils_1.loadConfig)();
|
|
16
17
|
const shouldUseSourceMap = isDev || Boolean(process.env.GENERATE_SOURCEMAP);
|
|
17
18
|
const publicPath = (0, ssr_server_utils_1.getOutputPublicPath)();
|
|
18
19
|
(0, base_1.getBaseConfig)(chain, false);
|
|
@@ -89,6 +90,14 @@ const getClientWebpack = (chain) => {
|
|
|
89
90
|
chain.when(generateAnalysis, chain => {
|
|
90
91
|
chain.plugin('analyze').use(BundleAnalyzerPlugin);
|
|
91
92
|
});
|
|
93
|
+
chain.when(isDev, chain => {
|
|
94
|
+
chain.plugin('fast-refresh').use(new ReactRefreshWebpackPlugin({
|
|
95
|
+
overlay: {
|
|
96
|
+
sockHost: host,
|
|
97
|
+
sockPort: fePort
|
|
98
|
+
}
|
|
99
|
+
}));
|
|
100
|
+
});
|
|
92
101
|
chain.plugin('WriteAsyncManifest').use(class WriteAsyncChunkManifest {
|
|
93
102
|
apply(compiler) {
|
|
94
103
|
compiler.hooks.watchRun.tap('thisCompilation', async () => {
|
|
@@ -10,7 +10,7 @@ const create_router_1 = require("./create-router");
|
|
|
10
10
|
const context_1 = require("./context");
|
|
11
11
|
const { FeRoutes, layoutFetch, App, PrefixRouterBase } = create_router_1.Routes;
|
|
12
12
|
const clientRender = async () => {
|
|
13
|
-
var _a, _b
|
|
13
|
+
var _a, _b;
|
|
14
14
|
const IApp = App !== null && App !== void 0 ? App : function (props) {
|
|
15
15
|
return props.children;
|
|
16
16
|
};
|
|
@@ -30,9 +30,6 @@ const clientRender = async () => {
|
|
|
30
30
|
const WrappedComponent = (0, ssr_hoc_react_1.wrapComponent)(component);
|
|
31
31
|
return (React.createElement(react_router_dom_1.Route, { exact: true, key: path, path: path, render: () => React.createElement(WrappedComponent, { key: location.pathname }) }));
|
|
32
32
|
})))))), document.getElementById('app'));
|
|
33
|
-
if (!window.__USE_VITE__) {
|
|
34
|
-
(_d = (_c = module === null || module === void 0 ? void 0 : module.hot) === null || _c === void 0 ? void 0 : _c.accept) === null || _d === void 0 ? void 0 : _d.call(_c); // webpack 场景下的 hmr
|
|
35
|
-
}
|
|
36
33
|
};
|
|
37
34
|
exports.clientRender = clientRender;
|
|
38
35
|
if (!window.__disableClientRender__) {
|
|
@@ -15,7 +15,7 @@ const { FeRoutes, layoutFetch, PrefixRouterBase, state } = create_router_1.Route
|
|
|
15
15
|
const serialize = serializeWrap.default || serializeWrap;
|
|
16
16
|
const serverRender = async (ctx, config) => {
|
|
17
17
|
var _a;
|
|
18
|
-
const {
|
|
18
|
+
const { mode, parallelFetch, disableClientRender, prefix, isVite, isDev, clientPrefix } = config;
|
|
19
19
|
let path = ctx.request.path; // 这里取 pathname 不能够包含 queryString
|
|
20
20
|
const base = prefix !== null && prefix !== void 0 ? prefix : PrefixRouterBase; // 以开发者实际传入的为最高优先级
|
|
21
21
|
if (base) {
|
|
@@ -28,14 +28,9 @@ const serverRender = async (ctx, config) => {
|
|
|
28
28
|
If you create new folder or component file, please restart server by npm start
|
|
29
29
|
`);
|
|
30
30
|
}
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
if (!isVite || (isVite && !isDev)) {
|
|
35
|
-
// call it when webpack mode or vite prod mode
|
|
36
|
-
dynamicCssOrder = await (0, ssr_server_utils_1.addAsyncChunk)(dynamicCssOrder, routeItem.webpackChunkName);
|
|
37
|
-
}
|
|
38
|
-
}
|
|
31
|
+
const { fetch, webpackChunkName, component } = routeItem;
|
|
32
|
+
const dynamicCssOrder = await (0, ssr_server_utils_1.getAsyncCssChunk)(ctx, webpackChunkName);
|
|
33
|
+
const dynamicJsOrder = await (0, ssr_server_utils_1.getAsyncJsChunk)(ctx);
|
|
39
34
|
const manifest = await (0, ssr_server_utils_1.getManifest)(config);
|
|
40
35
|
const injectCss = [];
|
|
41
36
|
if (isVite && isDev) {
|
|
@@ -66,14 +61,13 @@ const serverRender = async (ctx, config) => {
|
|
|
66
61
|
__html: 'window.__USE_VITE__=true'
|
|
67
62
|
} }),
|
|
68
63
|
(isVite && isDev) && React.createElement("script", { type: "module", src: '/node_modules/ssr-plugin-react/esm/entry/client-entry.js', key: "vite-react-entry" }),
|
|
69
|
-
...
|
|
64
|
+
...dynamicJsOrder.map(js => manifest[js]).map(item => item && React.createElement("script", { key: item, src: item, type: isVite ? 'module' : '' }))
|
|
70
65
|
];
|
|
71
66
|
const staticList = {
|
|
72
67
|
injectCss,
|
|
73
68
|
injectScript
|
|
74
69
|
};
|
|
75
70
|
const isCsr = !!(mode === 'csr' || ((_a = ctx.request.query) === null || _a === void 0 ? void 0 : _a.csr));
|
|
76
|
-
const { component, fetch } = routeItem;
|
|
77
71
|
const Component = isCsr ? React.Fragment : (await component()).default;
|
|
78
72
|
if (isCsr) {
|
|
79
73
|
(0, ssr_server_utils_1.logGreen)(`Current path ${path} use csr render mode`);
|
package/cjs/tools/vite.js
CHANGED
|
@@ -6,7 +6,7 @@ const vite_1 = require("vite");
|
|
|
6
6
|
const ssr_server_utils_1 = require("ssr-server-utils");
|
|
7
7
|
const plugin_react_1 = require("@vitejs/plugin-react");
|
|
8
8
|
const vite_plugin_style_import_1 = require("vite-plugin-style-import");
|
|
9
|
-
const { getOutput,
|
|
9
|
+
const { getOutput, reactServerEntry, reactClientEntry, viteConfig, supportOptinalChaining, isDev, define, babelOptions } = (0, ssr_server_utils_1.loadConfig)();
|
|
10
10
|
const { clientOutPut, serverOutPut } = getOutput();
|
|
11
11
|
const styleImportConfig = {
|
|
12
12
|
include: ['**/*.vue', '**/*.ts', '**/*.js', '**/*.tsx', '**/*.jsx', /chunkName/],
|
|
@@ -51,14 +51,14 @@ const serverConfig = {
|
|
|
51
51
|
},
|
|
52
52
|
define: {
|
|
53
53
|
__isBrowser__: false,
|
|
54
|
-
...define === null || define === void 0 ? void 0 : define.
|
|
55
|
-
...define === null || define === void 0 ? void 0 : define.
|
|
54
|
+
...define === null || define === void 0 ? void 0 : define.base,
|
|
55
|
+
...define === null || define === void 0 ? void 0 : define.server
|
|
56
56
|
}
|
|
57
57
|
};
|
|
58
58
|
exports.serverConfig = serverConfig;
|
|
59
59
|
const clientConfig = {
|
|
60
60
|
...(0, ssr_server_utils_1.commonConfig)(),
|
|
61
|
-
base: isDev ? '/' :
|
|
61
|
+
base: isDev ? '/' : (0, ssr_server_utils_1.getOutputPublicPath)(),
|
|
62
62
|
esbuild: {
|
|
63
63
|
keepNames: true
|
|
64
64
|
},
|
|
@@ -83,8 +83,8 @@ const clientConfig = {
|
|
|
83
83
|
},
|
|
84
84
|
define: {
|
|
85
85
|
__isBrowser__: true,
|
|
86
|
-
...define === null || define === void 0 ? void 0 : define.
|
|
87
|
-
...define === null || define === void 0 ? void 0 : define.
|
|
86
|
+
...define === null || define === void 0 ? void 0 : define.base,
|
|
87
|
+
...define === null || define === void 0 ? void 0 : define.client
|
|
88
88
|
}
|
|
89
89
|
};
|
|
90
90
|
exports.clientConfig = clientConfig;
|
package/esm/config/base.js
CHANGED
|
@@ -4,9 +4,9 @@ import * as webpack from 'webpack';
|
|
|
4
4
|
const MiniCssExtractPlugin = require(loadModuleFromFramework('mini-css-extract-plugin'));
|
|
5
5
|
const WebpackBar = require('webpackbar');
|
|
6
6
|
const loadModule = loadModuleFromFramework;
|
|
7
|
-
const addBabelLoader = (chain, envOptions) => {
|
|
7
|
+
const addBabelLoader = (chain, envOptions, isServer) => {
|
|
8
8
|
var _a, _b;
|
|
9
|
-
const { babelOptions } = loadConfig();
|
|
9
|
+
const { babelOptions, isDev } = loadConfig();
|
|
10
10
|
chain.use('babel-loader')
|
|
11
11
|
.loader(loadModule('babel-loader'))
|
|
12
12
|
.options({
|
|
@@ -38,7 +38,7 @@ const addBabelLoader = (chain, envOptions) => {
|
|
|
38
38
|
[loadModule('@babel/plugin-proposal-private-methods'), { loose: true }],
|
|
39
39
|
[loadModule('@babel/plugin-proposal-private-property-in-object'), { loose: true }],
|
|
40
40
|
...(_b = babelOptions === null || babelOptions === void 0 ? void 0 : babelOptions.plugins) !== null && _b !== void 0 ? _b : []
|
|
41
|
-
]
|
|
41
|
+
].concat((!isServer && isDev) ? loadModule('react-refresh/babel') : [])
|
|
42
42
|
})
|
|
43
43
|
.end();
|
|
44
44
|
};
|
|
@@ -76,6 +76,13 @@ const getBaseConfig = (chain, isServer) => {
|
|
|
76
76
|
.exclude
|
|
77
77
|
.add(/node_modules|core-js/)
|
|
78
78
|
.end();
|
|
79
|
+
chain.module
|
|
80
|
+
.rule('mjs')
|
|
81
|
+
.test(/\.mjs/)
|
|
82
|
+
.include
|
|
83
|
+
.add(/node_modules/).end()
|
|
84
|
+
.type('javascript/auto')
|
|
85
|
+
.end();
|
|
79
86
|
const module = chain.module
|
|
80
87
|
.rule('compileBabelForExtraModule')
|
|
81
88
|
.test(/\.(js|mjs|jsx|ts|tsx)$/)
|
|
@@ -88,8 +95,8 @@ const getBaseConfig = (chain, isServer) => {
|
|
|
88
95
|
else {
|
|
89
96
|
babelForExtraModule = module.end().exclude.add(/core-js/).end();
|
|
90
97
|
}
|
|
91
|
-
addBabelLoader(babelModule, envOptions);
|
|
92
|
-
addBabelLoader(babelForExtraModule, envOptions);
|
|
98
|
+
addBabelLoader(babelModule, envOptions, isServer);
|
|
99
|
+
addBabelLoader(babelForExtraModule, envOptions, isServer);
|
|
93
100
|
setStyle(chain, /\.css$/, {
|
|
94
101
|
rule: 'css',
|
|
95
102
|
isServer,
|
package/esm/config/client.js
CHANGED
|
@@ -5,11 +5,12 @@ import { getBaseConfig } from './base';
|
|
|
5
5
|
const ModuleNotFoundPlugin = require('react-dev-utils/ModuleNotFoundPlugin');
|
|
6
6
|
const safePostCssParser = require('postcss-safe-parser');
|
|
7
7
|
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
|
|
8
|
+
const ReactRefreshWebpackPlugin = require('@pmmmwh/react-refresh-webpack-plugin');
|
|
8
9
|
const generateAnalysis = Boolean(process.env.GENERATE_ANALYSIS);
|
|
9
10
|
const loadModule = loadModuleFromFramework;
|
|
10
11
|
let asyncChunkMap = {};
|
|
11
12
|
const getClientWebpack = (chain) => {
|
|
12
|
-
const { isDev, chunkName, getOutput, cwd, useHash, chainClientConfig } = loadConfig();
|
|
13
|
+
const { isDev, chunkName, getOutput, cwd, useHash, chainClientConfig, host, fePort } = loadConfig();
|
|
13
14
|
const shouldUseSourceMap = isDev || Boolean(process.env.GENERATE_SOURCEMAP);
|
|
14
15
|
const publicPath = getOutputPublicPath();
|
|
15
16
|
getBaseConfig(chain, false);
|
|
@@ -86,6 +87,14 @@ const getClientWebpack = (chain) => {
|
|
|
86
87
|
chain.when(generateAnalysis, chain => {
|
|
87
88
|
chain.plugin('analyze').use(BundleAnalyzerPlugin);
|
|
88
89
|
});
|
|
90
|
+
chain.when(isDev, chain => {
|
|
91
|
+
chain.plugin('fast-refresh').use(new ReactRefreshWebpackPlugin({
|
|
92
|
+
overlay: {
|
|
93
|
+
sockHost: host,
|
|
94
|
+
sockPort: fePort
|
|
95
|
+
}
|
|
96
|
+
}));
|
|
97
|
+
});
|
|
89
98
|
chain.plugin('WriteAsyncManifest').use(class WriteAsyncChunkManifest {
|
|
90
99
|
apply(compiler) {
|
|
91
100
|
compiler.hooks.watchRun.tap('thisCompilation', async () => {
|
|
@@ -7,7 +7,7 @@ import { Routes } from './create-router';
|
|
|
7
7
|
import { AppContext } from './context';
|
|
8
8
|
const { FeRoutes, layoutFetch, App, PrefixRouterBase } = Routes;
|
|
9
9
|
const clientRender = async () => {
|
|
10
|
-
var _a, _b
|
|
10
|
+
var _a, _b;
|
|
11
11
|
const IApp = App !== null && App !== void 0 ? App : function (props) {
|
|
12
12
|
return props.children;
|
|
13
13
|
};
|
|
@@ -27,9 +27,6 @@ const clientRender = async () => {
|
|
|
27
27
|
const WrappedComponent = wrapComponent(component);
|
|
28
28
|
return (React.createElement(Route, { exact: true, key: path, path: path, render: () => React.createElement(WrappedComponent, { key: location.pathname }) }));
|
|
29
29
|
})))))), document.getElementById('app'));
|
|
30
|
-
if (!window.__USE_VITE__) {
|
|
31
|
-
(_d = (_c = module === null || module === void 0 ? void 0 : module.hot) === null || _c === void 0 ? void 0 : _c.accept) === null || _d === void 0 ? void 0 : _d.call(_c); // webpack 场景下的 hmr
|
|
32
|
-
}
|
|
33
30
|
};
|
|
34
31
|
if (!window.__disableClientRender__) {
|
|
35
32
|
// 如果服务端直出的时候带上该记号,则默认不进行客户端渲染,将处理逻辑交给上层
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
import { StaticRouter } from 'react-router-dom';
|
|
3
|
-
import { findRoute, getManifest, logGreen, normalizePath,
|
|
3
|
+
import { findRoute, getManifest, logGreen, normalizePath, getAsyncCssChunk, getAsyncJsChunk } from 'ssr-server-utils';
|
|
4
4
|
// @ts-expect-error
|
|
5
5
|
import * as serializeWrap from 'serialize-javascript';
|
|
6
6
|
// @ts-expect-error
|
|
@@ -12,7 +12,7 @@ const { FeRoutes, layoutFetch, PrefixRouterBase, state } = Routes;
|
|
|
12
12
|
const serialize = serializeWrap.default || serializeWrap;
|
|
13
13
|
const serverRender = async (ctx, config) => {
|
|
14
14
|
var _a;
|
|
15
|
-
const {
|
|
15
|
+
const { mode, parallelFetch, disableClientRender, prefix, isVite, isDev, clientPrefix } = config;
|
|
16
16
|
let path = ctx.request.path; // 这里取 pathname 不能够包含 queryString
|
|
17
17
|
const base = prefix !== null && prefix !== void 0 ? prefix : PrefixRouterBase; // 以开发者实际传入的为最高优先级
|
|
18
18
|
if (base) {
|
|
@@ -25,14 +25,9 @@ const serverRender = async (ctx, config) => {
|
|
|
25
25
|
If you create new folder or component file, please restart server by npm start
|
|
26
26
|
`);
|
|
27
27
|
}
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
if (!isVite || (isVite && !isDev)) {
|
|
32
|
-
// call it when webpack mode or vite prod mode
|
|
33
|
-
dynamicCssOrder = await addAsyncChunk(dynamicCssOrder, routeItem.webpackChunkName);
|
|
34
|
-
}
|
|
35
|
-
}
|
|
28
|
+
const { fetch, webpackChunkName, component } = routeItem;
|
|
29
|
+
const dynamicCssOrder = await getAsyncCssChunk(ctx, webpackChunkName);
|
|
30
|
+
const dynamicJsOrder = await getAsyncJsChunk(ctx);
|
|
36
31
|
const manifest = await getManifest(config);
|
|
37
32
|
const injectCss = [];
|
|
38
33
|
if (isVite && isDev) {
|
|
@@ -63,14 +58,13 @@ const serverRender = async (ctx, config) => {
|
|
|
63
58
|
__html: 'window.__USE_VITE__=true'
|
|
64
59
|
} }),
|
|
65
60
|
(isVite && isDev) && React.createElement("script", { type: "module", src: '/node_modules/ssr-plugin-react/esm/entry/client-entry.js', key: "vite-react-entry" }),
|
|
66
|
-
...
|
|
61
|
+
...dynamicJsOrder.map(js => manifest[js]).map(item => item && React.createElement("script", { key: item, src: item, type: isVite ? 'module' : '' }))
|
|
67
62
|
];
|
|
68
63
|
const staticList = {
|
|
69
64
|
injectCss,
|
|
70
65
|
injectScript
|
|
71
66
|
};
|
|
72
67
|
const isCsr = !!(mode === 'csr' || ((_a = ctx.request.query) === null || _a === void 0 ? void 0 : _a.csr));
|
|
73
|
-
const { component, fetch } = routeItem;
|
|
74
68
|
const Component = isCsr ? React.Fragment : (await component()).default;
|
|
75
69
|
if (isCsr) {
|
|
76
70
|
logGreen(`Current path ${path} use csr render mode`);
|
package/esm/tools/vite.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o;
|
|
2
2
|
import { build } from 'vite';
|
|
3
|
-
import { loadConfig, chunkNamePlugin, rollupOutputOptions, manifestPlugin, commonConfig, asyncOptimizeChunkPlugin } from 'ssr-server-utils';
|
|
3
|
+
import { loadConfig, chunkNamePlugin, rollupOutputOptions, manifestPlugin, commonConfig, asyncOptimizeChunkPlugin, getOutputPublicPath } from 'ssr-server-utils';
|
|
4
4
|
import react from '@vitejs/plugin-react';
|
|
5
5
|
import styleImport, { AndDesignVueResolve, VantResolve, ElementPlusResolve, NutuiResolve, AntdResolve } from 'vite-plugin-style-import';
|
|
6
|
-
const { getOutput,
|
|
6
|
+
const { getOutput, reactServerEntry, reactClientEntry, viteConfig, supportOptinalChaining, isDev, define, babelOptions } = loadConfig();
|
|
7
7
|
const { clientOutPut, serverOutPut } = getOutput();
|
|
8
8
|
const styleImportConfig = {
|
|
9
9
|
include: ['**/*.vue', '**/*.ts', '**/*.js', '**/*.tsx', '**/*.jsx', /chunkName/],
|
|
@@ -48,13 +48,13 @@ const serverConfig = {
|
|
|
48
48
|
},
|
|
49
49
|
define: {
|
|
50
50
|
__isBrowser__: false,
|
|
51
|
-
...define === null || define === void 0 ? void 0 : define.
|
|
52
|
-
...define === null || define === void 0 ? void 0 : define.
|
|
51
|
+
...define === null || define === void 0 ? void 0 : define.base,
|
|
52
|
+
...define === null || define === void 0 ? void 0 : define.server
|
|
53
53
|
}
|
|
54
54
|
};
|
|
55
55
|
const clientConfig = {
|
|
56
56
|
...commonConfig(),
|
|
57
|
-
base: isDev ? '/' :
|
|
57
|
+
base: isDev ? '/' : getOutputPublicPath(),
|
|
58
58
|
esbuild: {
|
|
59
59
|
keepNames: true
|
|
60
60
|
},
|
|
@@ -79,8 +79,8 @@ const clientConfig = {
|
|
|
79
79
|
},
|
|
80
80
|
define: {
|
|
81
81
|
__isBrowser__: true,
|
|
82
|
-
...define === null || define === void 0 ? void 0 : define.
|
|
83
|
-
...define === null || define === void 0 ? void 0 : define.
|
|
82
|
+
...define === null || define === void 0 ? void 0 : define.base,
|
|
83
|
+
...define === null || define === void 0 ? void 0 : define.client
|
|
84
84
|
}
|
|
85
85
|
};
|
|
86
86
|
const viteStart = async () => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ssr-plugin-react",
|
|
3
|
-
"version": "6.2.
|
|
3
|
+
"version": "6.2.14",
|
|
4
4
|
"description": "plugin-react for ssr",
|
|
5
5
|
"main": "./cjs/index.js",
|
|
6
6
|
"module": "./esm/index.js",
|
|
@@ -34,6 +34,7 @@
|
|
|
34
34
|
"@babel/plugin-proposal-optional-chaining": "^7.16.5",
|
|
35
35
|
"@babel/plugin-transform-runtime": "^7.9.6",
|
|
36
36
|
"@babel/preset-env": "^7.5.5",
|
|
37
|
+
"@pmmmwh/react-refresh-webpack-plugin": "^0.5.5",
|
|
37
38
|
"@vitejs/plugin-react": "^1.0.0",
|
|
38
39
|
"babel-loader": "^8.0.4",
|
|
39
40
|
"babel-plugin-import": "1.13.3",
|
|
@@ -54,10 +55,11 @@
|
|
|
54
55
|
"postcss-preset-env": "^7.0.0",
|
|
55
56
|
"postcss-safe-parser": "^6.0.0",
|
|
56
57
|
"react": "^17.0.1",
|
|
58
|
+
"react-dev-utils": "^11.0.4",
|
|
57
59
|
"react-dom": "^17.0.0",
|
|
60
|
+
"react-refresh": "^0.12.0",
|
|
58
61
|
"react-router": "^5.2.1",
|
|
59
62
|
"react-router-dom": "^5.1.2",
|
|
60
|
-
"react-dev-utils": "^11.0.4",
|
|
61
63
|
"serialize-javascript": "^6.0.0",
|
|
62
64
|
"ssr-client-utils": "^6.2.7",
|
|
63
65
|
"ssr-hoc-react": "^6.2.7",
|
package/src/config/base.ts
CHANGED
|
@@ -9,8 +9,8 @@ const MiniCssExtractPlugin = require(loadModuleFromFramework('mini-css-extract-p
|
|
|
9
9
|
const WebpackBar = require('webpackbar')
|
|
10
10
|
const loadModule = loadModuleFromFramework
|
|
11
11
|
|
|
12
|
-
const addBabelLoader = (chain: WebpackChain.Rule<WebpackChain.Module>, envOptions: any) => {
|
|
13
|
-
const { babelOptions } = loadConfig()
|
|
12
|
+
const addBabelLoader = (chain: WebpackChain.Rule<WebpackChain.Module>, envOptions: any, isServer: boolean) => {
|
|
13
|
+
const { babelOptions, isDev } = loadConfig()
|
|
14
14
|
chain.use('babel-loader')
|
|
15
15
|
.loader(loadModule('babel-loader'))
|
|
16
16
|
.options({
|
|
@@ -42,7 +42,7 @@ const addBabelLoader = (chain: WebpackChain.Rule<WebpackChain.Module>, envOption
|
|
|
42
42
|
[loadModule('@babel/plugin-proposal-private-methods'), { loose: true }],
|
|
43
43
|
[loadModule('@babel/plugin-proposal-private-property-in-object'), { loose: true }],
|
|
44
44
|
...babelOptions?.plugins ?? []
|
|
45
|
-
]
|
|
45
|
+
].concat((!isServer && isDev) ? loadModule('react-refresh/babel') : [])
|
|
46
46
|
})
|
|
47
47
|
.end()
|
|
48
48
|
}
|
|
@@ -85,6 +85,14 @@ const getBaseConfig = (chain: WebpackChain, isServer: boolean) => {
|
|
|
85
85
|
.add(/node_modules|core-js/)
|
|
86
86
|
.end()
|
|
87
87
|
|
|
88
|
+
chain.module
|
|
89
|
+
.rule('mjs')
|
|
90
|
+
.test(/\.mjs/)
|
|
91
|
+
.include
|
|
92
|
+
.add(/node_modules/).end()
|
|
93
|
+
.type('javascript/auto')
|
|
94
|
+
.end()
|
|
95
|
+
|
|
88
96
|
const module = chain.module
|
|
89
97
|
.rule('compileBabelForExtraModule')
|
|
90
98
|
.test(/\.(js|mjs|jsx|ts|tsx)$/)
|
|
@@ -98,8 +106,8 @@ const getBaseConfig = (chain: WebpackChain, isServer: boolean) => {
|
|
|
98
106
|
babelForExtraModule = module.end().exclude.add(/core-js/).end()
|
|
99
107
|
}
|
|
100
108
|
|
|
101
|
-
addBabelLoader(babelModule, envOptions)
|
|
102
|
-
addBabelLoader(babelForExtraModule, envOptions)
|
|
109
|
+
addBabelLoader(babelModule, envOptions, isServer)
|
|
110
|
+
addBabelLoader(babelForExtraModule, envOptions, isServer)
|
|
103
111
|
|
|
104
112
|
setStyle(chain, /\.css$/, {
|
|
105
113
|
rule: 'css',
|
package/src/config/client.ts
CHANGED
|
@@ -7,12 +7,13 @@ import { getBaseConfig } from './base'
|
|
|
7
7
|
const ModuleNotFoundPlugin = require('react-dev-utils/ModuleNotFoundPlugin')
|
|
8
8
|
const safePostCssParser = require('postcss-safe-parser')
|
|
9
9
|
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
|
|
10
|
+
const ReactRefreshWebpackPlugin = require('@pmmmwh/react-refresh-webpack-plugin')
|
|
10
11
|
const generateAnalysis = Boolean(process.env.GENERATE_ANALYSIS)
|
|
11
12
|
const loadModule = loadModuleFromFramework
|
|
12
13
|
let asyncChunkMap: Record<string, string[]> = {}
|
|
13
14
|
|
|
14
15
|
const getClientWebpack = (chain: WebpackChain) => {
|
|
15
|
-
const { isDev, chunkName, getOutput, cwd, useHash, chainClientConfig } = loadConfig()
|
|
16
|
+
const { isDev, chunkName, getOutput, cwd, useHash, chainClientConfig, host, fePort } = loadConfig()
|
|
16
17
|
const shouldUseSourceMap = isDev || Boolean(process.env.GENERATE_SOURCEMAP)
|
|
17
18
|
const publicPath = getOutputPublicPath()
|
|
18
19
|
getBaseConfig(chain, false)
|
|
@@ -92,6 +93,15 @@ const getClientWebpack = (chain: WebpackChain) => {
|
|
|
92
93
|
chain.when(generateAnalysis, chain => {
|
|
93
94
|
chain.plugin('analyze').use(BundleAnalyzerPlugin)
|
|
94
95
|
})
|
|
96
|
+
chain.when(isDev, chain => {
|
|
97
|
+
chain.plugin('fast-refresh').use(new ReactRefreshWebpackPlugin({
|
|
98
|
+
overlay: {
|
|
99
|
+
sockHost: host,
|
|
100
|
+
sockPort: fePort
|
|
101
|
+
}
|
|
102
|
+
}))
|
|
103
|
+
})
|
|
104
|
+
|
|
95
105
|
chain.plugin('WriteAsyncManifest').use(
|
|
96
106
|
class WriteAsyncChunkManifest {
|
|
97
107
|
apply (compiler: any) {
|
|
@@ -9,7 +9,6 @@ import { AppContext } from './context'
|
|
|
9
9
|
|
|
10
10
|
const { FeRoutes, layoutFetch, App, PrefixRouterBase } = Routes as ReactRoutesType
|
|
11
11
|
|
|
12
|
-
declare const module: any
|
|
13
12
|
declare const window: IWindow
|
|
14
13
|
|
|
15
14
|
const clientRender = async (): Promise<void> => {
|
|
@@ -44,9 +43,6 @@ const clientRender = async (): Promise<void> => {
|
|
|
44
43
|
</BrowserRouter>
|
|
45
44
|
, document.getElementById('app'))
|
|
46
45
|
|
|
47
|
-
if (!window.__USE_VITE__) {
|
|
48
|
-
module?.hot?.accept?.() // webpack 场景下的 hmr
|
|
49
|
-
}
|
|
50
46
|
}
|
|
51
47
|
if (!window.__disableClientRender__) {
|
|
52
48
|
// 如果服务端直出的时候带上该记号,则默认不进行客户端渲染,将处理逻辑交给上层
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as React from 'react'
|
|
2
2
|
import { StaticRouter } from 'react-router-dom'
|
|
3
|
-
import { findRoute, getManifest, logGreen, normalizePath,
|
|
3
|
+
import { findRoute, getManifest, logGreen, normalizePath, getAsyncCssChunk, getAsyncJsChunk } from 'ssr-server-utils'
|
|
4
4
|
import { ISSRContext, IConfig, ReactRoutesType, ReactESMFeRouteItem } from 'ssr-types-react'
|
|
5
5
|
// @ts-expect-error
|
|
6
6
|
import * as serializeWrap from 'serialize-javascript'
|
|
@@ -14,7 +14,7 @@ const { FeRoutes, layoutFetch, PrefixRouterBase, state } = Routes as ReactRoutes
|
|
|
14
14
|
const serialize = serializeWrap.default || serializeWrap
|
|
15
15
|
|
|
16
16
|
const serverRender = async (ctx: ISSRContext, config: IConfig): Promise<React.ReactElement> => {
|
|
17
|
-
const {
|
|
17
|
+
const { mode, parallelFetch, disableClientRender, prefix, isVite, isDev, clientPrefix } = config
|
|
18
18
|
let path = ctx.request.path // 这里取 pathname 不能够包含 queryString
|
|
19
19
|
const base = prefix ?? PrefixRouterBase // 以开发者实际传入的为最高优先级
|
|
20
20
|
if (base) {
|
|
@@ -29,15 +29,9 @@ const serverRender = async (ctx: ISSRContext, config: IConfig): Promise<React.Re
|
|
|
29
29
|
`)
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
dynamicCssOrder = cssOrder.concat([`${routeItem.webpackChunkName}.css`])
|
|
36
|
-
if (!isVite || (isVite && !isDev)) {
|
|
37
|
-
// call it when webpack mode or vite prod mode
|
|
38
|
-
dynamicCssOrder = await addAsyncChunk(dynamicCssOrder, routeItem.webpackChunkName)
|
|
39
|
-
}
|
|
40
|
-
}
|
|
32
|
+
const { fetch, webpackChunkName, component } = routeItem
|
|
33
|
+
const dynamicCssOrder = await getAsyncCssChunk(ctx, webpackChunkName)
|
|
34
|
+
const dynamicJsOrder = await getAsyncJsChunk(ctx)
|
|
41
35
|
const manifest = await getManifest(config)
|
|
42
36
|
|
|
43
37
|
const injectCss: JSX.Element[] = []
|
|
@@ -71,7 +65,7 @@ const serverRender = async (ctx: ISSRContext, config: IConfig): Promise<React.Re
|
|
|
71
65
|
__html: 'window.__USE_VITE__=true'
|
|
72
66
|
}} />,
|
|
73
67
|
(isVite && isDev) && <script type="module" src='/node_modules/ssr-plugin-react/esm/entry/client-entry.js' key="vite-react-entry" />,
|
|
74
|
-
...
|
|
68
|
+
...dynamicJsOrder.map(js => manifest[js]).map(item => item && <script key={item} src={item} type={isVite ? 'module' : ''}/>)
|
|
75
69
|
]
|
|
76
70
|
const staticList = {
|
|
77
71
|
injectCss,
|
|
@@ -79,7 +73,6 @@ const serverRender = async (ctx: ISSRContext, config: IConfig): Promise<React.Re
|
|
|
79
73
|
}
|
|
80
74
|
|
|
81
75
|
const isCsr = !!(mode === 'csr' || ctx.request.query?.csr)
|
|
82
|
-
const { component, fetch } = routeItem
|
|
83
76
|
const Component = isCsr ? React.Fragment : (await component()).default
|
|
84
77
|
|
|
85
78
|
if (isCsr) {
|
package/src/tools/vite.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { build, UserConfig } from 'vite'
|
|
2
|
-
import { loadConfig, chunkNamePlugin, rollupOutputOptions, manifestPlugin, commonConfig, asyncOptimizeChunkPlugin } from 'ssr-server-utils'
|
|
2
|
+
import { loadConfig, chunkNamePlugin, rollupOutputOptions, manifestPlugin, commonConfig, asyncOptimizeChunkPlugin, getOutputPublicPath } from 'ssr-server-utils'
|
|
3
3
|
import react from '@vitejs/plugin-react'
|
|
4
4
|
import styleImport, { AndDesignVueResolve, VantResolve, ElementPlusResolve, NutuiResolve, AntdResolve } from 'vite-plugin-style-import'
|
|
5
|
-
const { getOutput,
|
|
5
|
+
const { getOutput, reactServerEntry, reactClientEntry, viteConfig, supportOptinalChaining, isDev, define, babelOptions } = loadConfig()
|
|
6
6
|
const { clientOutPut, serverOutPut } = getOutput()
|
|
7
7
|
const styleImportConfig = {
|
|
8
8
|
include: ['**/*.vue', '**/*.ts', '**/*.js', '**/*.tsx', '**/*.jsx', /chunkName/],
|
|
@@ -47,14 +47,14 @@ const serverConfig: UserConfig = {
|
|
|
47
47
|
},
|
|
48
48
|
define: {
|
|
49
49
|
__isBrowser__: false,
|
|
50
|
-
...define?.
|
|
51
|
-
...define?.
|
|
50
|
+
...define?.base,
|
|
51
|
+
...define?.server
|
|
52
52
|
}
|
|
53
53
|
}
|
|
54
54
|
|
|
55
55
|
const clientConfig: UserConfig = {
|
|
56
56
|
...commonConfig(),
|
|
57
|
-
base: isDev ? '/' :
|
|
57
|
+
base: isDev ? '/' : getOutputPublicPath(),
|
|
58
58
|
esbuild: {
|
|
59
59
|
keepNames: true
|
|
60
60
|
},
|
|
@@ -79,8 +79,8 @@ const clientConfig: UserConfig = {
|
|
|
79
79
|
},
|
|
80
80
|
define: {
|
|
81
81
|
__isBrowser__: true,
|
|
82
|
-
...define?.
|
|
83
|
-
...define?.
|
|
82
|
+
...define?.base,
|
|
83
|
+
...define?.client
|
|
84
84
|
}
|
|
85
85
|
}
|
|
86
86
|
const viteStart = async () => {
|