Skip to content

Latest commit

 

History

History
243 lines (209 loc) · 7.6 KB

README.md

File metadata and controls

243 lines (209 loc) · 7.6 KB

monkey-react-scripts

Monkey react script runner: Customize react-scripts webpack config without eject or fork

Many of you want to add small change to your webpack config created by create-react-app. but you don't want to eject. or use other scripts like configurable-react-scripts or custom-react-scripts because of update delay.

With monkey-react-scripts you can use react-scripts configs, but monkey patched one. so you always have updated react-scripts.

☢ DANGER ☢

As @gaearon mentioned multiple times there, it's not good idea to extend it. From my point of view, I'm giving you gun, so try not to shot yourself, because probably nobody will help you. When you modify something, be completely sure what you doing!

source

Usage

  • use create-react-app and create your project, more-detail
npm install -g create-react-app

create-react-app my-app
cd my-app/
  • install monkey-react-scripts
npm install monkey-react-scripts --save-dev --save-exact
  • create webpack.monkey.js in root of your project. you can modify webpack config here.
module.exports = function (webpackConfig, isDevelopment) {
    // mutate webpackConfig
};
  • edit package.json and replace scripts
  "scripts": {
    "start": "monkey-react-scripts start",
    "build": "monkey-react-scripts build",
    "test": "monkey-react-scripts test --env=jsdom"
  }

How it works

I suggest you see scripts and bin folders. (less than 100 line of code)

Note: returned value of require function is mutable. so you can mutate that before real build/start script.

Snippets

You can use snippets if you want.

snippets:

  • addPlugin
  • findLoader
  • addBabelPlugins
  • addLoader
  • addExclude
  • createTextExtractor
  • getScssLoader

Example

Before use examples you should know what happen inside react-scripts webpack config. first see and read this files:

  • node_modules/react-scripts/config/webpack.config.dev.js
  • node_modules/react-scripts/config/webpack.config.prod.js

also you can log webpackConfig value.

// webpack.monkey.js
module.exports = function (webpackConfig, isDevelopment) {
    console.log(webpackConfig)
};

Webpack Visualizer

I love visualization so I add webpack-visualizer-plugin to my project

  • install plugin:
npm install webpack-visualizer-plugin --save-dev
  • add plugin to config (only at build)
// webpack.monkey.js
var Visualizer = require('webpack-visualizer-plugin');

module.exports = function (webpackConfig, isDevelopment) {
    if (!isDevelopment) {
        webpackConfig.plugins.push(new Visualizer());
    }
};
  • build
$ npm run build
// some output
$ tree build
build
├── asset-manifest.json
├── favicon.ico
├── index.html
├── static
│   ├── css
│   │   ├── main.9a0fe4f1.css
│   │   └── main.9a0fe4f1.css.map
│   ├── js
│   │   ├── main.373f9afc.js
│   │   └── main.373f9afc.js.map
│   └── media
│       └── logo.5d5d9eef.svg
└── stats.html                      <-- new file

Decorator support

If you love decorators, you can add decorator support:

  • install decorator plugin
npm install --save-dev babel-plugin-transform-decorators-legacy
  • edit webpack.monkey.js like this (copy findLoader, addBabelPlugins from snippets):
function findLoader(config, callback) {
    var index = config.module.loaders.findIndex(callback);
    if (index === -1) throw Error('Loader not found');
    return config.module.loaders[index];
}

function addBabelPlugins(webpackConfig, plugins) {
    var babelLoader = findLoader(webpackConfig, function (loader) {
        return loader.loader === 'babel'
    });
    babelLoader.query.plugins = (babelLoader.query.plugins || []).concat(plugins);
}

module.exports = function (webpackConfig, isDevelopment) {
    addBabelPlugins(webpackConfig, [
        require.resolve('babel-plugin-transform-decorators-legacy')
    ]);
};

related issues: #107, #167, #214, #309, #411, #1357

Relay support

  • install babel-relay-plugin:
npm install --save-dev babel-relay-plugin
  • add relayPlugin.js file:
const getBabelRelayPlugin = require('babel-relay-plugin');
const schemaData = require('./graphql.schema.json');
const relayPlugin = getBabelRelayPlugin(schemaData.data);
module.exports = relayPlugin;
  • edit webpack.monkey.js like this:
/* copy findLoader, addBabelPlugins from decorator example */
module.exports = function (webpackConfig, isDevelopment) {
    addBabelPlugins(webpackConfig, [
        require.resolve('./relayPlugin.js')
    ]);
};

related issues: #462, #662, #900

scss support

  • install node-sass and sass-loader:
npm install --save-dev node-sass sass-loader
  • edit webpack.monkey.js like this:
/* copy addExclude, findLoader, addLoader, getScssLoader, createTextExtractor from snippets */
module.exports = function (webpackConfig, isDevelopment) {
    addExclude(webpackConfig, /\.scss$/);
    addLoader(webpackConfig, getScssLoader(isDevelopment));
};

similar code for less or stylus.

related issues: #78, #115, #351, #412, #1509, #1639

postcss config

If you want change postcss config you can use this code.

module.exports = function (webpackConfig, isDevelopment) {
    webpackConfig.postcss = function () {
        const postcssFunc = webpackConfig.postcss;
        return [
            require('postcss-inline-rtl'),  // add new postcss plugin
            ...postcssFunc()                // keep cra postcss plugins
             ]
    };
};

TODOs

  • add helpers snippets
    • addPlugin
    • findLoader
    • addBabelPlugins
    • extract text webpack plugin
    • addExclude
    • addLoader
  • customize test runner (jest)
  • add more example
    • postcss
    • scss support
    • decorator support
    • relay support

Thanks

@svrcekmichal for configurable-react-scripts