-
Notifications
You must be signed in to change notification settings - Fork 385
/
Copy pathserverWebpackConfig.js
118 lines (100 loc) · 4.44 KB
/
serverWebpackConfig.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
// The source code including full typescript support is available at:
// https://github.com/shakacode/react_on_rails_tutorial_with_ssr_and_hmr_fast_refresh/blob/master/config/webpack/serverWebpackConfig.js
const { config } = require('shakapacker');
const commonWebpackConfig = require('./commonWebpackConfig');
const webpack = require('webpack');
const configureServer = () => {
// We need to use "merge" because the clientConfigObject, EVEN after running
// toWebpackConfig() is a mutable GLOBAL. Thus any changes, like modifying the
// entry value will result in changing the client config!
// Using webpack-merge into an empty object avoids this issue.
const serverWebpackConfig = commonWebpackConfig();
// We just want the single server bundle entry
const serverEntry = {
'server-bundle': serverWebpackConfig.entry['server-bundle'],
};
if (!serverEntry['server-bundle']) {
throw new Error(
"Create a pack with the file name 'server-bundle.js' containing all the server rendering files",
);
}
serverWebpackConfig.entry = serverEntry;
// Remove the mini-css-extract-plugin from the style loaders because
// the client build will handle exporting CSS.
// replace file-loader with null-loader
serverWebpackConfig.module.rules.forEach((loader) => {
if (loader.use && loader.use.filter) {
loader.use = loader.use.filter(
(item) => !(typeof item === 'string' && item.match(/mini-css-extract-plugin/)),
);
}
});
// No splitting of chunks for a server bundle
serverWebpackConfig.optimization = {
minimize: false,
};
serverWebpackConfig.plugins.unshift(new webpack.optimize.LimitChunkCountPlugin({ maxChunks: 1 }));
// Custom output for the server-bundle that matches the config in
// config/initializers/react_on_rails.rb
serverWebpackConfig.output = {
filename: 'server-bundle.js',
globalObject: 'this',
// If using the React on Rails Pro node server renderer, uncomment the next line
// libraryTarget: 'commonjs2',
path: config.outputPath,
publicPath: config.publicPath,
// https://webpack.js.org/configuration/output/#outputglobalobject
};
// Don't hash the server bundle b/c would conflict with the client manifest
// And no need for the MiniCssExtractPlugin
serverWebpackConfig.plugins = serverWebpackConfig.plugins.filter(
(plugin) =>
plugin.constructor.name !== 'WebpackAssetsManifest' &&
plugin.constructor.name !== 'MiniCssExtractPlugin' &&
plugin.constructor.name !== 'ForkTsCheckerWebpackPlugin',
);
// Configure loader rules for SSR
// Remove the mini-css-extract-plugin from the style loaders because
// the client build will handle exporting CSS.
// replace file-loader with null-loader
const rules = serverWebpackConfig.module.rules;
rules.forEach((rule) => {
if (Array.isArray(rule.use)) {
// remove the mini-css-extract-plugin and style-loader
rule.use = rule.use.filter((item) => {
let testValue;
if (typeof item === 'string') {
testValue = item;
} else if (typeof item.loader === 'string') {
testValue = item.loader;
}
return !(testValue.match(/mini-css-extract-plugin/) || testValue === 'style-loader');
});
const cssLoader = rule.use.find((item) => {
let testValue;
if (typeof item === 'string') {
testValue = item;
} else if (typeof item.loader === 'string') {
testValue = item.loader;
}
return testValue.includes('css-loader');
});
if (cssLoader && cssLoader.options) {
cssLoader.options.modules = { exportOnlyLocals: true };
}
// Skip writing image files during SSR by setting emitFile to false
} else if (rule.use && (rule.use.loader === 'url-loader' || rule.use.loader === 'file-loader')) {
rule.use.options.emitFile = false;
}
});
// eval works well for the SSR bundle because it's the fastest and shows
// lines in the server bundle which is good for debugging SSR
// The default of cheap-module-source-map is slow and provides poor info.
serverWebpackConfig.devtool = 'eval';
// If using the default 'web', then libraries like Emotion and loadable-components
// break with SSR. The fix is to use a node renderer and change the target.
// If using the React on Rails Pro node server renderer, uncomment the next line
// serverWebpackConfig.target = 'node'
return serverWebpackConfig;
};
module.exports = configureServer;