├── .gitignore ├── LICENSE ├── README.md ├── bin └── monkey-react-scripts.js ├── package.json ├── scripts ├── build.js ├── start.js ├── test.js └── utils │ └── cache.js └── snippets ├── README.md ├── cra-0.9.x.md ├── cra-1.x.x.md ├── cra-2.x.x.md ├── cra-3.x.x.md └── cra-4.x.x.md /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | 6 | # Runtime data 7 | pids 8 | *.pid 9 | *.seed 10 | 11 | # Directory for instrumented libs generated by jscoverage/JSCover 12 | lib-cov 13 | 14 | # Coverage directory used by tools like istanbul 15 | coverage 16 | 17 | # nyc test coverage 18 | .nyc_output 19 | 20 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 21 | .grunt 22 | 23 | # node-waf configuration 24 | .lock-wscript 25 | 26 | # Compiled binary addons (http://nodejs.org/api/addons.html) 27 | build/Release 28 | 29 | # Dependency directories 30 | node_modules 31 | jspm_packages 32 | 33 | # Optional npm cache directory 34 | .npm 35 | 36 | # Optional REPL history 37 | .node_repl_history 38 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 monkey-patches 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # monkey-react-scripts 2 | 3 | Monkey react script runner: Customize react-scripts webpack config without eject or fork 4 | 5 | Many of you want to add a small change to your webpack config created by create-react-app. but you don't want to eject. or 6 | use other scripts like [configurable-react-scripts][configurable-react-scripts] or 7 | [custom-react-scripts][custom-react-scripts] because of update delay. 8 | 9 | With monkey-react-scripts you can use react-scripts configs, but monkey patched one. so you always have updated 10 | react-scripts. 11 | 12 | ## ☢ DANGER ☢ 13 | 14 | > As [@gaearon](https://github.com/gaearon) mentioned multiple times there, it's not good idea to extend it. From my 15 | > point of view, I'm giving you gun, so try not to shot yourself, because probably nobody will help you. When you modify 16 | > something, be completely sure what you doing! 17 | 18 | [source][configurable-react-scripts] 19 | 20 | ## Usage 21 | 22 | - use create-react-app and create your project, [more detail][create-react-app] 23 | 24 | ``` 25 | npm install -g create-react-app 26 | 27 | create-react-app my-app 28 | cd my-app/ 29 | ``` 30 | 31 | - install monkey-react-scripts 32 | 33 | ``` 34 | npm install monkey-react-scripts --save-dev --save-exact 35 | ``` 36 | 37 | - create `webpack.monkey.js` in the root of your project. you can modify webpack config here. 38 | 39 | ```js 40 | module.exports = function(webpackConfig, isDevelopment) { 41 | // mutate webpackConfig 42 | }; 43 | ``` 44 | 45 | - edit `package.json` and replace scripts 46 | 47 | ``` 48 | "scripts": { 49 | "start": "monkey-react-scripts start", 50 | "build": "monkey-react-scripts build", 51 | "test": "monkey-react-scripts test" 52 | } 53 | ``` 54 | 55 | ## How it works 56 | 57 | I suggest you see [scripts](scripts) and [bin](bin) folders. (less than 100 line of code) 58 | 59 | Note: returned value of `require` function is mutable. so you can mutate that before real build/start script. 60 | 61 | ## Snippets 62 | 63 | You can use [snippets](snippets/cra-4.x.x.md) if you want. 64 | 65 | snippets: 66 | 67 | - `addPlugin` 68 | - `findRule` 69 | - `findBabelRule` 70 | 71 | ## Example 72 | 73 | Before use examples, you should know what happens inside react-scripts webpack config. 74 | first, see and read this files: 75 | 76 | - `node_modules/react-scripts/config/webpack.config.dev.js` 77 | - `node_modules/react-scripts/config/webpack.config.prod.js` 78 | 79 | also, you can log `webpackConfig` value. 80 | 81 | ```js 82 | // webpack.monkey.js 83 | module.exports = function(webpackConfig, isDevelopment) { 84 | console.log(webpackConfig); 85 | }; 86 | ``` 87 | 88 | Also, you can find complete examples at [monkey-react-scripts-example] repo 89 | 90 | ### Enable `.babelrc` 91 | 92 | The `.babelrc` file is enabled for tests if you have `webpack.monkey.js` file. also, you can enable `.babelrc` for build and start: 93 | 94 | - edit `webpack.monkey.js` like this (copy `findRule`, `findBabelRule` from [snippets](snippets/cra-4.x.x.md)): 95 | 96 | ```js 97 | function findRule(webpackConfig, callback) { 98 | /* snippet codes */ 99 | } 100 | 101 | function findBabelRule(webpackConfig, callback) { 102 | /* snippet codes */ 103 | } 104 | 105 | module.exports = function(webpackConfig, isDevelopment) { 106 | const babelRule = findBabelRule(webpackConfig); 107 | babelRule.options.babelrc = true; 108 | }; 109 | ``` 110 | 111 | ### Webpack Visualizer 112 | 113 | I love visualization so, I add [webpack-visualizer-plugin][webpack-visualizer] to my project 114 | 115 | - install plugin: 116 | 117 | ``` 118 | npm install webpack-visualizer-plugin --save-dev 119 | ``` 120 | 121 | - add the plugin to config (only at build time) 122 | 123 | ```js 124 | // webpack.monkey.js 125 | var Visualizer = require("webpack-visualizer-plugin"); 126 | 127 | module.exports = function(webpackConfig, isDevelopment) { 128 | if (!isDevelopment) { 129 | webpackConfig.plugins.push(new Visualizer()); 130 | } 131 | }; 132 | ``` 133 | 134 | - build 135 | 136 | ``` 137 | $ npm run build 138 | // some output 139 | $ tree build 140 | build 141 | ├── asset-manifest.json 142 | ├── favicon.ico 143 | ├── index.html 144 | ├── static 145 | │   ├── css 146 | │   ├── js 147 | │   └── media 148 | └── stats.html <-- new file 149 | ``` 150 | 151 | ### Decorator support 152 | 153 | If you love decorators, you can add decorator support: 154 | 155 | - install decorator plugin 156 | 157 | ``` 158 | npm install --save-dev @babel/plugin-proposal-decorators 159 | ``` 160 | 161 | - edit `.babelrc` like this: 162 | 163 | ```json 164 | { 165 | "plugins": [["@babel/plugin-proposal-decorators", { "legacy": true }]] 166 | } 167 | ``` 168 | 169 | related issues: [#107][107], [#167][167], [#214][214], [#309][309], [#411][411], [#1357][1357] 170 | 171 | ### Relay support 172 | 173 | - install `babel-plugin-relay` 174 | 175 | ``` 176 | yarn add --dev babel-plugin-relay 177 | ``` 178 | 179 | - edit `.babelrc` like this: 180 | 181 | ```json 182 | { 183 | "plugins": ["relay"] 184 | } 185 | ``` 186 | 187 | and continue [relay documentation][relay-setup] steps. 188 | 189 | if you are using relay classic you can see [old readme][old-relay-support] and get some ideas. 190 | 191 | related issues: [#462][462], [#662][662], [#900][900] 192 | 193 | ## postcss config 194 | 195 | If you want to change postcss config you can use this code. 196 | 197 | ```js 198 | // add rtl css support 199 | // find postCssLoader 200 | const postCssFunction = postCssLoader.options.plugins; 201 | postCssLoader.options.plugins = () => { 202 | return [...postCssFunction(), require("postcss-inline-rtl")]; 203 | }; 204 | ``` 205 | 206 | you can find more detail in [this file][css-patch] 207 | 208 | ## TODOs 209 | 210 | - [ ] customize test runner (jest) 211 | - [x] add more example 212 | - [x] relay support 213 | 214 | ## compatibility 215 | 216 | | react-scripts | monkey-react-scripts | 217 | | :-----------: | :------------------: | 218 | | 0.9.x | 0.0.5 | 219 | | 1.x.x | 0.1.0 | 220 | | 2.0.0 - 2.1.1 | 0.1.2 | 221 | | 2.1.2 | 0.1.4 | 222 | | 3.0.0 | 0.2.0 | 223 | | 4.0.0 | 0.3.0 | 224 | | 5.0.0 | 5.0.0-0 | 225 | 226 | ## Thanks 227 | 228 | @svrcekmichal for [configurable-react-scripts][configurable-react-scripts] 229 | 230 | [create-react-app]: https://github.com/facebookincubator/create-react-app#tldr 231 | [webpack-visualizer]: https://github.com/chrisbateman/webpack-visualizer 232 | [configurable-react-scripts]: https://github.com/svrcekmichal/configurable-react-scripts 233 | [custom-react-scripts]: https://github.com/kitze/custom-react-scripts 234 | [relay-setup]: https://facebook.github.io/relay/docs/en/installation-and-setup.html 235 | [monkey-react-scripts-example]: https://github.com/monkey-patches/monkey-react-scripts-example 236 | [old-relay-support]: https://github.com/monkey-patches/monkey-react-scripts/blob/b7380bbb873d637cdd6cf911de9f696b90b608fe/README.md#relay-support 237 | [css-patch]: https://github.com/monkey-patches/monkey-react-scripts-example/blob/d759030325ca2d638b1ea0dd44e51655b88d5022/webpack-helpers/cssPatch.js 238 | [107]: https://github.com/facebookincubator/create-react-app/issues/107 239 | [167]: https://github.com/facebookincubator/create-react-app/issues/167 240 | [214]: https://github.com/facebookincubator/create-react-app/issues/214 241 | [309]: https://github.com/facebookincubator/create-react-app/issues/309 242 | [411]: https://github.com/facebookincubator/create-react-app/issues/411 243 | [1357]: https://github.com/facebookincubator/create-react-app/issues/1357 244 | [462]: https://github.com/facebookincubator/create-react-app/issues/462 245 | [662]: https://github.com/facebookincubator/create-react-app/pull/662 246 | [900]: https://github.com/facebookincubator/create-react-app/issues/900 247 | -------------------------------------------------------------------------------- /bin/monkey-react-scripts.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 'use strict'; 3 | 4 | // Makes the script crash on unhandled rejections instead of silently 5 | // ignoring them. In the future, promise rejections that are not handled will 6 | // terminate the Node.js process with a non-zero exit code. 7 | process.on('unhandledRejection', err => { 8 | throw err; 9 | }); 10 | 11 | const spawn = require('react-dev-utils/crossSpawn'); 12 | const args = process.argv.slice(2); 13 | 14 | const scriptIndex = args.findIndex( 15 | x => x === 'build' || x === 'eject' || x === 'start' || x === 'test' 16 | ); 17 | const script = scriptIndex === -1 ? args[0] : args[scriptIndex]; 18 | const nodeArgs = scriptIndex > 0 ? args.slice(0, scriptIndex) : []; 19 | 20 | if (['build', 'start', 'test'].includes(script)) { 21 | const result = spawn.sync( 22 | process.execPath, 23 | nodeArgs 24 | .concat(require.resolve('../scripts/' + script)) 25 | .concat(args.slice(scriptIndex + 1)), 26 | { stdio: 'inherit' } 27 | ); 28 | if (result.signal) { 29 | if (result.signal === 'SIGKILL') { 30 | console.log( 31 | 'The build failed because the process exited too early. ' + 32 | 'This probably means the system ran out of memory or someone called ' + 33 | '`kill -9` on the process.' 34 | ); 35 | } else if (result.signal === 'SIGTERM') { 36 | console.log( 37 | 'The build failed because the process exited too early. ' + 38 | 'Someone might have called `kill` or `killall`, or the system could ' + 39 | 'be shutting down.' 40 | ); 41 | } 42 | process.exit(1); 43 | } 44 | process.exit(result.status); 45 | } else { 46 | console.log('Unknown script "' + script + '".'); 47 | } 48 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "monkey-react-scripts", 3 | "version": "5.0.0-0", 4 | "description": "Monkey react script runner", 5 | "main": "index.js", 6 | "repository": "git@github.com:monkey-patches/monkey-react-scripts.git", 7 | "author": "Seyyed Morteza Moosavi ", 8 | "license": "MIT", 9 | "files": [ 10 | "bin", 11 | "scripts" 12 | ], 13 | "bin": { 14 | "monkey-react-scripts": "./bin/monkey-react-scripts.js" 15 | }, 16 | "peerDependencies": { 17 | "react-scripts": ">=5.0.0" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /scripts/build.js: -------------------------------------------------------------------------------- 1 | process.env.BABEL_ENV = 'production'; 2 | process.env.NODE_ENV = 'production'; 3 | 4 | require('react-scripts/config/env'); 5 | 6 | const patchModule = require('./utils/cache'); 7 | 8 | const fs = require('fs-extra'); 9 | const path = require('path'); 10 | 11 | const chalk = require('chalk'); 12 | const appPath = require('react-scripts/config/paths').appPath; 13 | const webpackMonkeyPath = path.resolve(appPath, 'webpack.monkey.js'); 14 | 15 | const originalConfigFactory = require('react-scripts/config/webpack.config'); 16 | 17 | if (fs.existsSync(webpackMonkeyPath)) { 18 | console.log(chalk.yellow('WARNING! You are using modified webpack config!')); 19 | const configPatch = require(webpackMonkeyPath); 20 | patchModule('react-scripts/config/webpack.config', (...args) => { 21 | const webpackConfig = originalConfigFactory(...args); 22 | return configPatch(webpackConfig, false) || webpackConfig; 23 | }); 24 | } 25 | 26 | require('react-scripts/scripts/build'); 27 | -------------------------------------------------------------------------------- /scripts/start.js: -------------------------------------------------------------------------------- 1 | process.env.BABEL_ENV = 'production'; 2 | process.env.NODE_ENV = 'production'; 3 | 4 | require('react-scripts/config/env'); 5 | 6 | const patchModule = require('./utils/cache'); 7 | 8 | const fs = require('fs-extra'); 9 | const path = require('path'); 10 | 11 | const chalk = require('chalk'); 12 | const appPath = require('react-scripts/config/paths').appPath; 13 | const webpackMonkeyPath = path.resolve(appPath, 'webpack.monkey.js'); 14 | 15 | const originalConfigFactory = require('react-scripts/config/webpack.config'); 16 | 17 | if (fs.existsSync(webpackMonkeyPath)) { 18 | console.log(chalk.yellow('WARNING! You are using modified webpack config!')); 19 | const configPatch = require(webpackMonkeyPath); 20 | patchModule('react-scripts/config/webpack.config', (...args) => { 21 | const webpackConfig = originalConfigFactory(...args); 22 | return configPatch(webpackConfig, true) || webpackConfig; 23 | }); 24 | } 25 | 26 | require('react-scripts/scripts/start'); 27 | -------------------------------------------------------------------------------- /scripts/test.js: -------------------------------------------------------------------------------- 1 | process.env.BABEL_ENV = 'test'; 2 | process.env.NODE_ENV = 'test'; 3 | process.env.PUBLIC_URL = ''; 4 | 5 | require('react-scripts/config/env'); 6 | 7 | const patchModule = require('./utils/cache'); 8 | 9 | const fs = require('fs-extra'); 10 | const path = require('path'); 11 | 12 | const chalk = require('chalk'); 13 | const appPath = require('react-scripts/config/paths').appPath; 14 | const webpackMonkeyPath = path.resolve(appPath, 'webpack.monkey.js'); 15 | 16 | require('react-scripts/config/jest/babelTransform.js') 17 | 18 | if (fs.existsSync(webpackMonkeyPath)) { 19 | console.log(chalk.yellow('WARNING! .babelrc file is enabled!')); 20 | const babelJest = require('babel-jest').default; 21 | 22 | const hasJsxRuntime = (() => { 23 | if (process.env.DISABLE_NEW_JSX_TRANSFORM === 'true') { 24 | return false; 25 | } 26 | 27 | try { 28 | require.resolve('react/jsx-runtime'); 29 | return true; 30 | } catch (e) { 31 | return false; 32 | } 33 | })(); 34 | 35 | const babelTransform = babelJest.createTransformer({ 36 | presets: [ 37 | [ 38 | require.resolve('babel-preset-react-app'), 39 | { 40 | runtime: hasJsxRuntime ? 'automatic' : 'classic', 41 | }, 42 | ], 43 | ], 44 | babelrc: true, 45 | configFile: false, 46 | }); 47 | 48 | patchModule('react-scripts/config/jest/babelTransform.js', babelTransform); 49 | } 50 | 51 | require('react-scripts/scripts/test'); -------------------------------------------------------------------------------- /scripts/utils/cache.js: -------------------------------------------------------------------------------- 1 | function patchModule(key, value) { 2 | const configModule = require.cache[require.resolve(key)]; 3 | configModule.exports = value; 4 | } 5 | 6 | module.exports = patchModule; -------------------------------------------------------------------------------- /snippets/README.md: -------------------------------------------------------------------------------- 1 | # Code snippets 2 | 3 | You need know what happen in monkey brain. So Snippets is better than helpers 4 | 5 | - [snippets for cra@0.9.x](cra-0.9.x.md) 6 | - [snippets for cra@1.x.x](cra-1.x.x.md) 7 | - [snippets for cra@2.x.x](cra-2.x.x.md) 8 | - [snippets for cra@3.x.x](cra-3.x.x.md) 9 | - [snippets for cra@4.x.x](cra-4.x.x.md) 10 | -------------------------------------------------------------------------------- /snippets/cra-0.9.x.md: -------------------------------------------------------------------------------- 1 | # Code snippets for create-react-app 0.9.x 2 | useful codes you can copy and use in webpack.monkey.js file. 3 | 4 | In real project I copy some of them in other file and use require function: 5 | 6 | ## webpack plugin 7 | 8 | Add webpack plugin 9 | ```js 10 | function addPlugin(config, plugin) { 11 | config.plugins.push(plugin); 12 | } 13 | ``` 14 | 15 | ## Find loader 16 | 17 | ```js 18 | function findLoader(config, callback) { 19 | var index = config.module.loaders.findIndex(callback); 20 | if (index === -1) throw Error('Loader not found'); 21 | return config.module.loaders[index]; 22 | } 23 | ``` 24 | 25 | ## Add Babel plugin 26 | requirement: `findLoader` 27 | ```js 28 | function addBabelPlugins(webpackConfig, plugins) { 29 | var babelLoader = findLoader(webpackConfig, function (loader) { 30 | return loader.loader === 'babel' 31 | }); 32 | babelLoader.query.plugins = (babelLoader.query.plugins || []).concat(plugins); 33 | } 34 | 35 | ``` 36 | ## addLoader 37 | ```js 38 | function addLoader(webpackConfig, loader) { 39 | webpackConfig.module.loaders.push(loader); 40 | } 41 | ``` 42 | 43 | ## addExclude 44 | cra use url loader for all unknown files. 45 | requirement: `findLoader` 46 | ```js 47 | function addExclude(webpackConfig, regex) { 48 | const loader = findLoader(webpackConfig, function(rule) { 49 | return rule.loader === 'url' 50 | }); 51 | loader.exclude.push(regex); 52 | } 53 | ``` 54 | 55 | ## create extract text plugin 56 | 57 | ```js 58 | const ExtractTextPlugin = require('extract-text-webpack-plugin'); 59 | const paths = require('react-scripts/config/paths'); 60 | const publicPath = paths.servedPath; 61 | const shouldUseRelativeAssetPaths = publicPath === './'; 62 | const cssFilename = 'static/css/[name].[contenthash:8].css'; 63 | 64 | 65 | const createTextExtractor = function (fallback, use) { 66 | const extractTextPluginOptions = {}; 67 | if (shouldUseRelativeAssetPaths) { 68 | extractTextPluginOptions.publicPath = Array(cssFilename.split('/').length).join('../') 69 | } 70 | 71 | return ExtractTextPlugin.extract(fallback, use, extractTextPluginOptions); 72 | }; 73 | 74 | ``` 75 | 76 | ## scss config 77 | requirement: `createTextExtractor` 78 | 79 | ```js 80 | function getScssLoader(isDevelopment) { 81 | 82 | if (isDevelopment) { 83 | return { 84 | test: /\.scss$/, 85 | loader: 'style!css?importLoaders=1!postcss!sass' 86 | }; 87 | } 88 | return { 89 | test: /\.scss$/, 90 | loader: createTextExtractor('style', 'css?importLoaders=1!postcss!sass'), 91 | }; 92 | } 93 | 94 | ``` 95 | -------------------------------------------------------------------------------- /snippets/cra-1.x.x.md: -------------------------------------------------------------------------------- 1 | # Code snippets for create-react-app 1.x.x 2 | useful codes you can copy and use in webpack.monkey.js file. 3 | 4 | In real project I copy some of them in other file and use require function: 5 | 6 | ## webpack plugin 7 | 8 | Add webpack plugin 9 | ```js 10 | function addPlugin(webpackConfig, plugin) { 11 | webpackConfig.plugins.push(plugin); 12 | } 13 | ``` 14 | ## Find Rule 15 | 16 | ```js 17 | function findRule(webpackConfig, callback) { 18 | const rules = webpackConfig.module.rules[1].oneOf; 19 | const index = rules.findIndex(callback); 20 | if (index === -1) throw Error('Loader not found'); 21 | return rules[index] 22 | } 23 | ``` 24 | 25 | ## Add Babel plugin 26 | requirement: `findRule` 27 | ```js 28 | function addBabelPlugins(webpackConfig, plugins) { 29 | // find babel rule 30 | const babelRule = findRule(webpackConfig, (rule) => { 31 | return ('' + rule.test === '' + /\.(js|jsx|mjs)$/) 32 | }); 33 | babelRule.options.plugins = (babelRule.options.plugins || []).concat(plugins); 34 | } 35 | ``` 36 | 37 | ## add Rule 38 | ```js 39 | function addRule (webpackConfig, rule) { 40 | const rules = webpackConfig.module.rules[1].oneOf; 41 | rules.splice(rules.length - 1, 0, rule); // add before exclude rule 42 | } 43 | ``` 44 | -------------------------------------------------------------------------------- /snippets/cra-2.x.x.md: -------------------------------------------------------------------------------- 1 | # Code snippets for create-react-app 1.x.x 2 | useful codes you can copy and use in webpack.monkey.js file. 3 | 4 | In real project I copy some of them in other file and use require function: 5 | 6 | ## webpack plugin 7 | 8 | Add webpack plugin 9 | ```js 10 | function addPlugin(webpackConfig, plugin) { 11 | webpackConfig.plugins.push(plugin); 12 | } 13 | ``` 14 | ## Find Rule 15 | 16 | ```js 17 | function findRule(webpackConfig, callback) { 18 | const rules = webpackConfig.module.rules[3].oneOf; 19 | const index = rules.findIndex(callback); 20 | if (index === -1) throw Error('Loader not found'); 21 | return rules[index] 22 | } 23 | ``` 24 | 25 | ## find Babel rule 26 | requirement: `findRule` 27 | ```js 28 | function findBabelRule(webpackConfig, plugins) { 29 | // find babel rule 30 | const babelRule = findRule(webpackConfig, (rule) => { 31 | return ('' + rule.test === '' + /\.(js|jsx)$/) 32 | }); 33 | return babelRule; 34 | } 35 | ``` 36 | -------------------------------------------------------------------------------- /snippets/cra-3.x.x.md: -------------------------------------------------------------------------------- 1 | # Code snippets for create-react-app 1.x.x 2 | useful codes you can copy and use in webpack.monkey.js file. 3 | 4 | In real project I copy some of them in other file and use require function: 5 | 6 | ## webpack plugin 7 | 8 | Add webpack plugin 9 | ```js 10 | function addPlugin(webpackConfig, plugin) { 11 | webpackConfig.plugins.push(plugin); 12 | } 13 | ``` 14 | ## Find Rule 15 | 16 | ```js 17 | function findRule(webpackConfig, callback) { 18 | const rules = webpackConfig.module.rules[2].oneOf; 19 | const index = rules.findIndex(callback); 20 | if (index === -1) throw Error('Loader not found'); 21 | return rules[index] 22 | } 23 | ``` 24 | 25 | ## find Babel rule 26 | requirement: `findRule` 27 | ```js 28 | function findBabelRule(webpackConfig, plugins) { 29 | // find babel rule 30 | const babelRule = findRule(webpackConfig, (rule) => { 31 | return ('' + rule.test === '' + /\.(js|jsx)$/) 32 | }); 33 | return babelRule; 34 | } 35 | ``` 36 | -------------------------------------------------------------------------------- /snippets/cra-4.x.x.md: -------------------------------------------------------------------------------- 1 | # Code snippets for create-react-app 1.x.x 2 | useful codes you can copy and use in webpack.monkey.js file. 3 | 4 | In real project I copy some of them in other file and use require function: 5 | 6 | ## webpack plugin 7 | 8 | Add webpack plugin 9 | ```js 10 | function addPlugin(webpackConfig, plugin) { 11 | webpackConfig.plugins.push(plugin); 12 | } 13 | ``` 14 | ## Find Rule 15 | 16 | ```js 17 | function findRule(webpackConfig, callback) { 18 | const rules = webpackConfig.module.rules[1].oneOf; 19 | const index = rules.findIndex(callback); 20 | if (index === -1) throw Error('Loader not found'); 21 | return rules[index] 22 | } 23 | ``` 24 | 25 | ## find Babel rule 26 | requirement: `findRule` 27 | ```js 28 | function findBabelRule(webpackConfig, plugins) { 29 | // find babel rule 30 | const babelRule = findRule(webpackConfig, (rule) => { 31 | return ('' + rule.test === '' + /\.(js|jsx)$/) 32 | }); 33 | return babelRule; 34 | } 35 | ``` 36 | --------------------------------------------------------------------------------