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+ */
15const webpackConfig = require ( "./webpack.typescript" ) ;
26const webpack = require ( "webpack" ) ;
37const 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 = / \. ( t s | t s x | j s | j s x | c s s | s c s s | h t m l | x m l ) $ / ;
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 = / \. ( t s | t s x ) $ / ;
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 : / \. [ j t ] s ( x ? ) $ / ,
55- exclude : / n o d e _ m o d u l e s / ,
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 = / \. ( t s | t s x | j s | c s s | s c s s | h t m l | x m l ) $ / ;
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