Skip to content

Commit 354b935

Browse files
authored
fix(webpack): react config (NativeScript#8822)
1 parent d51abef commit 354b935

File tree

2 files changed

+59
-83
lines changed

2 files changed

+59
-83
lines changed

packages/webpack/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@nativescript/webpack",
3-
"version": "3.0.1",
3+
"version": "3.0.2",
44
"main": "index",
55
"description": "Webpack plugin for NativeScript",
66
"homepage": "https://nativescript.org",
Lines changed: 58 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
/**
2+
* @see https://github.com/NativeScript/NativeScript/tree/feat/ns7-finishing-touches/packages/webpack/templates
3+
* @see https://github.com/NativeScript/NativeScript/pull/8801/files
4+
*/
15
const webpackConfig = require("./webpack.typescript");
26
const webpack = require("webpack");
37
const ReactRefreshWebpackPlugin = require('@pmmmwh/react-refresh-webpack-plugin');
@@ -8,105 +12,77 @@ module.exports = (env) => {
812
const production = env.production;
913
const isAnySourceMapEnabled = !!env.sourceMap || !!env.hiddenSourceMap;
1014

11-
const babelOptions = {
12-
sourceMaps: isAnySourceMapEnabled ? "inline" : false,
13-
babelrc: false,
14-
presets: [
15-
// https://github.com/Microsoft/TypeScript-Babel-Starter
16-
"@babel/env",
17-
"@babel/typescript",
18-
"@babel/react"
19-
],
20-
plugins: [
21-
...(
22-
hmr && !production ?
23-
[
24-
require.resolve('react-refresh/babel')
25-
] :
26-
[]
27-
),
28-
["@babel/plugin-proposal-class-properties", { loose: true }]
29-
]
30-
};
31-
3215
const baseConfig = webpackConfig(env);
3316

34-
// Remove ts-loader as we'll be using Babel to transpile the TypeScript instead.
35-
baseConfig.module.rules = baseConfig.module.rules.filter((rule) => {
36-
const isTsLoader = rule.use && rule.use.loader === "ts-loader";
37-
return !isTsLoader;
38-
});
39-
40-
// Modify "nativescript-dev-webpack/hmr/hot-loader" to test for .tsx files
41-
// (and also js(x) files, which it should have been doing to begin with!)
42-
baseConfig.module.rules.some(rule => {
43-
const isNativeScriptDevWebpackHotLoader = rule.use === "nativescript-dev-webpack/hmr/hot-loader";
44-
45-
if(isNativeScriptDevWebpackHotLoader){
46-
rule.test = /\.(ts|tsx|js|jsx|css|scss|html|xml)$/;
47-
}
48-
49-
return isNativeScriptDevWebpackHotLoader; // Break loop once we've found the one.
50-
});
17+
/** Find the rule for transpiling ts files ("ts-loader"), and modify it to test for .tsx files too. */
18+
const tsxRule = baseConfig.module.rules.find(rule => rule.use && rule.use.loader === "ts-loader");
19+
tsxRule.test = /\.(ts|tsx)$/;
20+
tsxRule.use = [
21+
/**
22+
* Add React Refresh HMR support.
23+
* @see https://github.com/pmmmwh/react-refresh-webpack-plugin/blob/55028c6355b31e697e21bf3e9a48613a7b94bee7/examples/typescript-without-babel/webpack.config.js#L18-L21
24+
*/
25+
hmr && !production && {
26+
loader: "babel-loader",
27+
options: {
28+
sourceMaps: isAnySourceMapEnabled ? "inline" : false,
29+
babelrc: false,
30+
plugins: ['react-refresh/babel']
31+
}
32+
},
33+
tsxRule.use,
34+
].filter(Boolean);
5135

52-
baseConfig.module.rules.push(
53-
{
54-
test: /\.[jt]s(x?)$/,
55-
exclude: /node_modules/,
56-
use: [
57-
{
58-
loader: "babel-loader",
59-
options: babelOptions
60-
}
61-
],
62-
}
36+
/**
37+
* Modify "nativescript-dev-webpack/hmr/hot-loader" to test for .tsx files
38+
* (and also js files, which it should have been doing to begin with!)
39+
*/
40+
const nativeScriptDevWebpackHotLoader = baseConfig.module.rules.find(rule =>
41+
rule.use === "@nativescript/webpack/hmr/hot-loader"
6342
);
43+
nativeScriptDevWebpackHotLoader.test = /\.(ts|tsx|js|css|scss|html|xml)$/;
6444

65-
baseConfig.resolve.extensions = [".ts", ".tsx", ".js", ".jsx", ".scss", ".css"];
45+
/** We don't officially support JSX. Makes the webpack config rather more complicated to set up. */
46+
baseConfig.resolve.extensions = [".tsx", ...baseConfig.resolve.extensions];
6647
baseConfig.resolve.alias["react-dom"] = "react-nativescript";
6748

68-
// Remove ForkTsCheckerWebpackPlugin because, now that we're using Babel, we'll leave type-checking to the IDE instead.
69-
baseConfig.plugins = baseConfig.plugins.filter(plugin => {
70-
const isForkTsCheckerWebpackPlugin = plugin && plugin.constructor && plugin.constructor.name === "ForkTsCheckerWebpackPlugin";
71-
return !isForkTsCheckerWebpackPlugin;
72-
});
49+
/** Augment NativeScript's existing DefinePlugin definitions with a few more of our own. */
50+
const existingDefinePlugin = baseConfig.plugins.find(plugin =>
51+
plugin && plugin.constructor && plugin.constructor.name === "DefinePlugin"
52+
);
53+
baseConfig.plugins.splice(
54+
baseConfig.plugins.indexOf(existingDefinePlugin),
55+
1,
56+
new webpack.DefinePlugin({
57+
...existingDefinePlugin.definitions,
58+
/** For various libraries in the React ecosystem. */
59+
"__DEV__": production ? "false" : "true",
60+
"__TEST__": "false",
61+
/**
62+
* Primarily for React Fast Refresh plugin, but technically the allowHmrInProduction option could be used instead.
63+
* Worth including anyway, as there are plenty of Node libraries that use this flag.
64+
*/
65+
"process.env.NODE_ENV": JSON.stringify(production ? "production" : "development"),
66+
}),
67+
);
7368

74-
// Augment NativeScript's existing DefinePlugin definitions with a few more of our own.
75-
let existingDefinePlugin;
76-
baseConfig.plugins = baseConfig.plugins.filter(plugin => {
77-
const isDefinePlugin = plugin && plugin.constructor && plugin.constructor.name === "DefinePlugin";
78-
existingDefinePlugin = plugin;
79-
return !isDefinePlugin;
80-
});
81-
const newDefinitions = {
82-
...existingDefinePlugin.definitions,
83-
/* For various libraries in the React ecosystem. */
84-
"__DEV__": production ? "false" : "true",
85-
"__TEST__": "false",
86-
/*
87-
* Primarily for React Fast Refresh plugin, but technically the forceEnable option could be used instead.
88-
* Worth including anyway, as there are plenty of Node libraries that use this flag.
89-
*/
90-
"process.env.NODE_ENV": JSON.stringify(production ? "production" : "development"),
91-
};
92-
baseConfig.plugins.unshift(new webpack.DefinePlugin(newDefinitions));
93-
94-
/**
95-
* Set forceEnable to `true` if you want to use HMR on a production build.
96-
*/
97-
const forceEnable = false;
98-
if(hmr && (!production || forceEnable)){
69+
if(hmr && !production){
9970
baseConfig.plugins.push(new ReactRefreshWebpackPlugin({
10071
/**
10172
* Maybe one day we'll implement an Error Overlay, but the work involved is too daunting for now.
10273
* @see https://github.com/pmmmwh/react-refresh-webpack-plugin/issues/79#issuecomment-644324557
10374
*/
10475
overlay: false,
105-
forceEnable,
76+
/**
77+
* If you (temporarily) want to enable HMR on a production build:
78+
* 1) Set `forceEnable` to `true`
79+
* 2) Remove the `!production` condition on `tsxRule` to ensure that babel-loader gets used.
80+
*/
81+
forceEnable: false,
10682
}));
10783
} else {
10884
baseConfig.plugins = baseConfig.plugins.filter(p => !(p && p.constructor && p.constructor.name === "HotModuleReplacementPlugin"));
10985
}
11086

11187
return baseConfig;
112-
};
88+
};

0 commit comments

Comments
 (0)