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.
@@ -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,
@@ -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, _c, _d;
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 { cssOrder, jsOrder, dynamic, mode, parallelFetch, disableClientRender, prefix, isVite, isDev, clientPrefix } = config;
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
- let dynamicCssOrder = cssOrder;
32
- if (dynamic) {
33
- dynamicCssOrder = cssOrder.concat([`${routeItem.webpackChunkName}.css`]);
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
- ...jsOrder.map(js => manifest[js]).map(item => item && React.createElement("script", { key: item, src: item, type: isVite ? 'module' : '' }))
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, prefix, reactServerEntry, reactClientEntry, viteConfig, supportOptinalChaining, isDev, define, babelOptions } = (0, ssr_server_utils_1.loadConfig)();
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.server,
55
- ...define === null || define === void 0 ? void 0 : define.base
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 ? '/' : prefix,
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.client,
87
- ...define === null || define === void 0 ? void 0 : define.base
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;
@@ -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,
@@ -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, _c, _d;
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, addAsyncChunk } from 'ssr-server-utils';
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 { cssOrder, jsOrder, dynamic, mode, parallelFetch, disableClientRender, prefix, isVite, isDev, clientPrefix } = config;
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
- let dynamicCssOrder = cssOrder;
29
- if (dynamic) {
30
- dynamicCssOrder = cssOrder.concat([`${routeItem.webpackChunkName}.css`]);
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
- ...jsOrder.map(js => manifest[js]).map(item => item && React.createElement("script", { key: item, src: item, type: isVite ? 'module' : '' }))
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, prefix, reactServerEntry, reactClientEntry, viteConfig, supportOptinalChaining, isDev, define, babelOptions } = loadConfig();
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.server,
52
- ...define === null || define === void 0 ? void 0 : define.base
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 ? '/' : prefix,
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.client,
83
- ...define === null || define === void 0 ? void 0 : define.base
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.11",
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",
@@ -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',
@@ -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, addAsyncChunk } from 'ssr-server-utils'
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 { cssOrder, jsOrder, dynamic, mode, parallelFetch, disableClientRender, prefix, isVite, isDev, clientPrefix } = config
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
- let dynamicCssOrder = cssOrder
33
-
34
- if (dynamic) {
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
- ...jsOrder.map(js => manifest[js]).map(item => item && <script key={item} src={item} type={isVite ? 'module' : ''}/>)
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, prefix, reactServerEntry, reactClientEntry, viteConfig, supportOptinalChaining, isDev, define, babelOptions } = loadConfig()
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?.server,
51
- ...define?.base
50
+ ...define?.base,
51
+ ...define?.server
52
52
  }
53
53
  }
54
54
 
55
55
  const clientConfig: UserConfig = {
56
56
  ...commonConfig(),
57
- base: isDev ? '/' : prefix,
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?.client,
83
- ...define?.base
82
+ ...define?.base,
83
+ ...define?.client
84
84
  }
85
85
  }
86
86
  const viteStart = async () => {