This article documents the react project template, React-Starter, used to develop the React – CNode. Create-react-app is an excellent official scaffolding that already provides a wealth of functionality. This template is based on the project eject created by create-React-App, and has been customized according to individual needs without affecting the original functionality.

directory

Using webpack2

Migrating from v1 to V2 can be used to replace webpack V1 with Webpack V2. The differences between Webpack V1 and V2 are not described here. For details, see the official documentation for Migrating from V1 to V2.

Note that webpack2 has built-in support for ES2015 modules, so set the modules configured for ES2015 in Babel to false. This is also necessary to support hot updates of the React component.

  "babel": {
    "presets": [
      [
        "es2015",
        {
          "modules": false
        }
      ],
      "stage-0",
      "react"
    ]
  }Copy the code

Es2015 + stage-0 + react is used instead of the original babel-preth-react-app, because babel-preact-react-app does not support some experimental language features, so use it at your own cost.

Multiple entry

Create-react-app is implemented every time a new project is created, especially if it is only a simple page. This is cumbersome because create-react-app supports only one file entry, so it is necessary to support multiple entries.

To support multiple entries, only a few changes to config/paths.js are required.

Read NPM command parameters:

let appname = process.argv.find(arg => arg.indexOf('app=') === 0);
appname = appname ? appname.split('=')[1] : '';Copy the code

Then modify the output path:

  appBuild: resolveApp(`build/${appname}`),
  appPublic: resolveApp(`public/${appname}`),
  appHtml: resolveApp(`public/${appname}/index.html`),
  appIndexJs: resolveApp(`src/${appname}/index.js`),Copy the code

┑( ̄  ̄)┍. To use multiple entries, you need to create directories with the same name under SRC and public respectively. For example:

  • public
    • react
    • react-router
  • src
    • react
    • react-router

Then add the code files to each directory. For details, see the react-Starter project structure.

Add the — app=appname parameter to the NPM command as shown in the following example:

  • npm start -- app=appname
  • npm run build -- app=appname
  • serve -s build/appname

Separate third-party libraries

I’ll call it Appconfig.js and fix it in its own project directory at the same level as index.js. It won’t be found anywhere else

Adding a config file is easy. First you need a fsExistsSync method to determine if the config file exists and then add the config file path to config/paths.js:

appConfigJs: resolveApp(`src/${appname}/appconfig.js`)Copy the code

Then just configure webpack.config.dev.js and webpack.config.prod.js to introduce the appconfig.js file to load the configuration in webpack:

const appConfig = fsExistsSync(paths.appConfigJs) ? require(paths.appConfigJs) : {};
const appConfigEntry = appConfig.entry;Copy the code

Finally, change the entry configuration of webpack.config.prod.js to:

Object.assign({
    main: [
      require.resolve('./polyfills'),
      paths.appIndexJs
    ]
}, appConfigEntry)Copy the code

Add CommonsChunkPlugin to your plugins:

    new webpack.optimize.CommonsChunkPlugin({
      names: ['main', 'manifest'].concat(Object.keys(appConfigEntry))
    }),Copy the code

The change to webpack.config.dev.js is similar, here I fixed the application file package named main.js.

For library files that want to be packaged in a file, such as the react and react-dom libraries packaged together into a react.js file, and vendors. Js, you can configure the following in appconfig.js:

module.exports = {
  entry: {
    react: ['react', 'react-dom'],
    vendors: ['rxjs', 'immutable', 'axios', 'react-redux', 'react-router-dom', 'redux', 'redux-observable']
  }
};Copy the code

This is very necessary. For specific reasons, please refer to the official description of code-splitting-libraries (Chinese document code-splitter-libraries).

Supports hot update of the React component

React Hot Loader 3 is used to support hot updates to the React component.

  1. inwebpack.config.dev.jsTo the entry configuration'react-hot-loader/patch', note that it needs to be placed at the top, i.e. :
    entry: Object.assign({
        main: [
            'react-hot-loader/patch',
            require.resolve('react-dev-utils/webpackHotDevClient'),
            require.resolve('./polyfills'),
            paths.appIndexJs
        ]
    }, appConfigEntry)Copy the code
  2. Add it to the configuration plugins of babel-Loaderreact-hot-loader/babel, that is:
      {
        test: /\.(js|jsx)$/,
        include: paths.appSrc,
        loader: 'babel-loader',
        options: {
          cacheDirectory: true,
          plugins: [
            'react-hot-loader/babel'
          ]
        }
      }Copy the code
  3. <AppContainer/>Is a component that handles module reloading and error handling. The root component of the application should be nested as a child component in AppContainer. In a production environment, AppContainer is automatically disabled and only its children are returned. The specific code is as follows:
    import React from 'react';
    import ReactDOM from 'react-dom';
    import {AppContainer} from 'react-hot-loader';
    
    import App from './App';
    import './index.css';
    
    const root = document.getElementById("root");
    
    const render = (Component) => {
        ReactDOM.render(
            <AppContainer>
                <Component />
            </AppContainer>,
            root
        );
    };
    
    render(App);
    
    // Hot Module Replacement API
    if (module.hot) {
        module.hot.accept('./App', () => {
            render(App);
        });
    }Copy the code

    For details, see an examplereact-routerOr the samplereact.

Official React Hot Loader3 User Guide

The React component is loaded on demand

You can use lazy-load-react to load components on demand, use lazy-load-react to load files, and also support hot updates! Built into this project template, it can be used in other projects through:

npm install lazy-load-react

Usage:

import lazyme from 'lazy-load-react';

const HomePage = lazyme(() => System.import('./HomePage'));

<Route exact path="/" component={HomePage}/>Copy the code

For details, see the example React-router App or React-Cnode App.

Supporting aliases

Similar to configuring third-party library files, you need to do this in Appconfig.js.

For details about how to use alias, see the official document resolve. Alias. You can also configure other configuration items in resolve in the official document. Resolve Chinese documents. The following is an example of the appconfig.js configuration:

module.exports = {
  entry: {
    react: ['react', 'react-dom'],
    vendors: ['rxjs', 'immutable', 'axios', 'react-redux', 'react-router-dom', 'redux', 'redux-observable']
  }
  resolve: {
    alias: {
      'Containers': path.resolve(__dirname, 'containers/')
    }
  }
};Copy the code

This has both advantages and disadvantages. The advantages are that it simplifies the path of importing modules, e.g

import Page from '.. /.. /containers/page';Copy the code

Can be written as

import Page from 'Containers/page';Copy the code

However, after doing this, the editor may not be able to parse the path, affecting functions such as path correctness verification, file moving and modifying corresponding file references, so it is at your discretion.


Did this article help you? Welcome to join the front End learning Group wechat group: