webpack4 中的最新 React百口桶实战运用设置指南!

《webpack4 中的最新 React百口桶实战运用设置指南!》

想浏览更多优良文章请猛戳GitHub博客,一年百来篇优良文章等着你!

最新React百口桶实战运用设置指南

这篇文档 是吕小明先生连系以往的项目履历 加上自身自身对react webpack redux明白写下的总结文档,统共耗时一周总结下来的,愿望能对读者能够有收成, 我是在这基础多些加工!

目次

1.版本申明

2.目次构造

3.初始化项目

4.webpack

5.react

6.设置loader(sass,jsx))

7.引入babel

8.运用HtmlWebpackPlugin

9.redux

10.运用webpack-dev-server

11.多进口页面设置

12.怎样明白entry point(bundle),chunk,module

13.多进口页面html设置

14.模块热替代(Hot Module Replacement)

15.运用ESLint

16.运用react-router

17.运用redux-thunk

18.运用axios和async/await

19.Code Splitting

20.运用CommonsChunkPlugin

版本申明

因为构建相干比方webpack,babel等更新的较快,所以本教程以下面种种模块的版本号为主,切勿随意马虎修正或更新版本。

"dependencies": {
    "babel-core": "^6.26.3",
    "babel-eslint": "^8.2.3",
    "babel-loader": "^7.1.4",
    "babel-plugin-transform-async-to-generator": "^6.24.1",
    "babel-plugin-transform-runtime": "^6.23.0",
    "babel-preset-es2015": "^6.24.1",
    "babel-preset-react": "^6.24.1",
    "babel-preset-stage-0": "^6.24.1",
    "babel-preset-stage-3": "^6.24.1",
    "css-loader": "^0.28.11",
    "eslint": "^4.19.1",
    "eslint-loader": "^2.0.0",
    "eslint-plugin-react": "^7.9.1",
    "file-loader": "^1.1.11",
    "history": "^4.7.2",
    "html-webpack-plugin": "^3.2.0",
    "react": "^16.4.0",
    "react-dom": "^16.4.0",
    "react-hot-loader": "^4.0.0",
    "react-redux": "^5.0.7",
    "react-router-dom": "^4.3.1",
    "react-router-redux": "^5.0.0-alpha.9",
    "redux": "^4.0.0",
    "sass-loader": "^7.0.3",
    "style-loader": "^0.21.0",
    "url-loader": "^1.0.1",
    "webpack": "^4.12.0",
    "webpack-cli": "^3.0.3",
    "webpack-dev-server": "^3.1.1"
}

目次构造

开辟和宣布版本的设置文件是离开的,多进口页面的目次构造。

react-family/
    |
    |──dist/                                    * 宣布版本构建输出途径
    |
    |──dev/                                     * 调试版本构建输出途径
    |
    |──src/                                     * 东西函数
    |     |
    |     |—— component/                        * 各页面公用组件
    |     |
    |     |—— page/                             * 页面代码
    |     |      |—— index/                     * 页面代码
    |     |      |        |—— Main/             * 组件代码
    |     |      |        |       |—— Main.jsx  * 组件jsx
    |     |      |        |       |—— Main.scss * 组件css
    |     |      |
    |     |      |—— detail/                    * 页面代码
    |     |
    |     |—— static/                           * 静态文件js,css
    |
    |
    |──webpack.config.build.js                  * 宣布版本运用的webpack设置文件
    |──webpack.config.dev.js                    * 调试版本运用的webpack设置文件
    |──.eslint                                  * eslint设置文件
    |__.babelrc                                 * babel设置文件
    
    
    

初始化项目

1.竖立文件夹

mkdir react-family-bucket

2.初始化npm

cd react-family-bucket
npm init

假如有特殊须要,能够填入自身的设置,一同回车下来,会天生一个package.json,内里是你项目的基础信息,背面的npm依靠装置也会设置在这里。

webpack

1.装置webpack

npm install webpack@4.12.0 --save
or
npm install webpack@4.12.0 --g

--save 是将当前webpack装置到react-family-bucket下的/node_modules。

--g 是将当前webpack装置到全局下面,能够在node的装置目次下找到全局的/node_modules。

2.设置webopack设置文件

touch webpack.config.dev.js

3.新建一个app.js

touch app.js

写入基础的webpack设置,能够参考这里

const path = require('path');
const srcRoot = './src';
module.exports = {

    // 输入设置
    entry: [
      './app.js'
    ],,

    // 输出设置
    output: {
        path: path.resolve(__dirname, './dev'),

        filename: 'bundle.min.js'
    },
};

3.实行webpack敕令

假如是全局装置:

webpack --config webpack.config.dev.js

假如是当前目次装置:

./node_modules/.bin/webpack --config webpack.config.dev.js

为了轻易我们运用,能够在package.json中 scripts 增添实行敕令:

"scripts": {
  "dev": "./node_modules/.bin/webpack --config webpack.config.dev.js",
},

实行npm run dev敕令以后,会发明须要装置webpack-cli,(webpack4以后须要装置这个)

npm install webpack-cli --save

装置后,实行 npm run dev 会发明掌握台有个正告 WARNING in configuration ,去除WARNING in configuration 正告,在webpack.config.dev.js 增添一个设置即可:

...
mode: 'development'
...

胜利以后会在dev下面天生bundle.min.js代表一般。

假如想要动态监听文件变化须要在敕令背面增添 –watch。

react

1.装置react

npm install react react-dom --save

2.竖立page目次和index页面文件:

mkdir src
mkdir page
cd page

3.竖立index


mkdir index
cd index & touch index.js & touch index.html

index.js

import ReactDom from 'react-dom';
import Main from './Main/Main.jsx';

ReactDom.render(<Main />, document.getElementById('root'));

index.html

<!DOCTYPE html>
<html>
<head>
    <title>index</title>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no">

</head>
<body>
<div id="root"></div>
</body>
</html>

4.竖立Main组件

import React from 'react';

class Main extends React.Component {

    constructor(props) {
        super(props);
    }

    render() {
        return (<div>Main</div>);
    }
}
export default Main;

5.修正webpack设置进口文件

entry: [
    path.resolve(srcRoot,'./page/index/index.js')
],

设置loader

1.处置惩罚款式文件须要这些loader:

npm install css-loader sass-loader style-loader file-loader --save

设置:

module: {
    // 加载器设置
    rules: [
        { test: /\.css$/, use: ['style-loader', 'css-loader'], include: path.resolve(srcRoot)},
        { test: /\.scss$/, use: ['style-loader', 'css-loader', 'sass-loader'], include: path.resolve(srcRoot)}
    ]
},

2.url-loader 处置惩罚处置惩罚静态文件

npm install url-loader --save

设置:

module: {
    // 加载器设置
    rules: [
        { test: /\.(png|jpg|jpeg)$/, use: 'url-loader?limit=8192&name=images/[name].[hash].[ext]', include: path.resolve(srcRoot)}
    ]
},

limit:示意凌驾若干就运用base64来替代,单元是byte

name:能够设置图片的途径,称号和是不是运用hash 详细参考这里

引入babel

bebel是用来剖析es6语法或许是es7语法分剖析器,让开辟者能够运用新的es语法,同时支撑jsx,vue等多种框架。

1.装置babel

npm install babel-core babel-loader --save

设置:

module: {
    // 加载器设置
    rules: [
        { test: /\.(js|jsx)$/, use: [{loader:'babel-loader'}] ,include: path.resolve(srcRoot)},
    ]
},

2.babel设置文件:.babelrc

touch .babelrc

设置:

{
    "presets": [
        "es2015",
        "react",
        "stage-0"
    ],
    "plugins": []
}

babel支撑自定义的预设(presets)或插件(plugins),只要设置了这两个才能让babel见效,零丁的装置babel是无意义的。

presets:代表babel支撑那种语法(就是你用那种语法写),优先级是从下往上,state-0|1|2|..代表有许多没有列入规范的语法回已state-x示意,参考这里

plugins:代表babel剖析的时刻运用哪些插件,作用和presets相似,优先级是从上往下。

顺次装置:

npm install babel-preset-es2015 babel-preset-react babel-preset-stage-0 --save

3.babel-polyfill是什么?

我们之前运用的babel,babel-loader 默许只转换新的 JavaScript 语法,而不转换新的 API。比方,Iterator、Generator、Set、Maps、Proxy、Reflect、Symbol、Promise 等全局对象,以及一些定义在全局对象上的要领(比方 Object.assign)都不会转译。假如想运用这些新的对象和要领,必需运用 babel-polyfill,为当前环境供应一个垫片。

npm install --save babel-polyfill

4.transform-runtime 有什么区别?

当运用babel-polyfill时有一些问题:

  • 默许会引入一切babel支撑的新语法,如许就会致使你的文件代码异常巨大。
  • 经由历程向全局对象和内置对象的prototype上增添要领来杀青目的,形成全局变量污染。

这时候就须要transform-runtime来帮我们有挑选性的引入:

npm install --save babel-plugin-transform-runtime

设置文件:


{
  "plugins": [
    ["transform-runtime", {
      "helpers": false,
      "polyfill": false,
      "regenerator": true,
      "moduleName": "babel-runtime"
    }]
  ]
}


运用HtmlWebpackPlugin

记得我们之前新建的index.html么 我们实行构建敕令以后并没有将index.html打包到dev目次下 我们须要HtmlWebpackPlugin来将我们output的js和html连系起来:

npm install html-webpack-plugin --save

设置:

const HtmlWebpackPlugin = require('html-webpack-plugin');
...
plugins: [
    new HtmlWebpackPlugin({
        filename: path.resolve(devPath, 'index.html'),
        template: path.resolve(srcRoot, './page/index/index.html'),
    })
]

filename:能够设置html输出的途径和文件名
template:能够设置已哪一个html文件为模版

更多参数设置能够参考这里

redux

关于redux的运用能够参考阮一峰先生的入门教程

1.装置redux

npm install redux react-redux --save

1.新建reducers,actions目次和文件

|—— index/                          
|—— Main/                   * 组件代码
|       |—— Main.jsx        * 组件jsx
|       |—— Main.scss       * 组件css
|
|—— actions/ 
|       |—— actionTypes.js  * action常量
|       |—— todoAction.js   * action
|
|—— reducers/ 
|       |—— todoReducer.js  * reducer
|
|—— store.js
|
|—— index.js

2.修正代码,引入redux,这里以一个redux todo为demo例子:

index.js

import ReactDom from 'react-dom';
import React from 'react';
import Main from './Main/Main.jsx';
import store from './store.js';
import { Provider } from 'react-redux';

ReactDom.render(
    <Provider store={store}>
        <Main />
    </Provider>
, document.getElementById('root'));  

store.js

import { createStore } from 'redux';
import todoReducer from './reducers/todoReducer.js';

const store = createStore(todoReducer);

export default store;  

tabReducer.js

    import { ADD_TODO } from '../actions/actionTypes.js';
    
    const initialState = {
          todoList: []
    };
    
    const addTodo = (state, action) => {
    
      return { ...state, todoList: state.todoList.concat(action.obj) }
    }
    
    const todoReducer = (state = initialState, action) => {
      switch(action.type) {
        case ADD_TODO: return addTodo(state, action);
        default: return state;
      }
    };
    export default todoReducer;

Main.jsx

import React from 'react';
import { connect } from 'react-redux';
import { addTodo } from '../actions/todoAction.js';

class Main extends React.Component {

    onClick(){
        let text = this.refs.input;

        this.props.dispatch(addTodo({
            text: text.value
        }))
    }
    render() {
        return (
            <div>
                <input ref="input" type="text"></input>
                <button onClick={()=>this.onClick()}>提交</button>
                <ul>
                {this.props.todoList.map((item, index)=>{
                    return <li key={index}>{item.text}</li>
                })}
                </ul>
            </div>
        );
    }
}

export default connect(
    state => ({
        todoList: state.todoList
    })
)(Main);

todoAction.js

import { ADD_TODO } from './actionTypes.js';

export const addTodo = (obj) => {
  return {
    type: ADD_TODO,
    obj: obj
  };
};

运用webpack-dev-server

webpack-dev-server是一个小型的Node.js Express服务器,它运用webpack-dev-middleware来服务于webpack的包。

1.装置

npm install webpack-dev-server --save

修正在package.json中增添的实行敕令:

"scripts": {
  "dev": "./node_modules/.bin/webpack-dev-server --config webpack.config.dev.js",
},

2.设置webpack设置文件:

devServer: {
    "contentBase": devPath,
    "compress": true,
},

contentBase: 示意server文件的根目次
compress: 示意开启gzip

更多的设置文档参考这里

  • webpack-dev-server默许情况下会将output的内容放在内存中,是看不到物理的文件的,假如想要看到物理的dev下面的文件能够装置write-file-webpack-plugin这个插件。
  • webpack-dev-server默许会开启livereload功用

3.devtool功用:

详细来说增添了devtool: ‘inline-source-map’以后,应用source-map你在chrome掌握台看到的source源码都是真正的源码,未紧缩,未编译前的代码,没有增添,你看到的代码是实在的紧缩过,编译过的代码,更多devtool的设置能够参考这里

多进口文件设置

在之前的设置中,都是基于单进口页面设置的,entry和output只要一个文件,然则现实项目许多情况下是多页面的,在设置多页面时,有2中要领能够挑选:

1.在entry进口设置时,传入对象而不是零丁数组,output时应用[name]关键字来辨别输出文件比方:

entry: {
    index: [path.resolve(srcRoot,'./page/index/index1.js'),path.resolve(srcRoot,'./page/index/index2.js')],
    detail: path.resolve(srcRoot,'./page/detail/detail.js'),
    home: path.resolve(srcRoot,'./page/home/home.js'),
},
output: {
    path: path.resolve(__dirname, './dev'),

    filename: '[name].min.js'
},

2.经由历程node动态遍历须要entry point的目次,来动态天生entry:

const pageDir = path.resolve(srcRoot, 'page');
function getEntry() {
    let entryMap = {};

    fs.readdirSync(pageDir).forEach((pathname)=>{
        let fullPathName = path.resolve(pageDir, pathname);
        let stat = fs.statSync(fullPathName);
        let fileName = path.resolve(fullPathName, 'index.js');

        if (stat.isDirectory() && fs.existsSync(fileName)) {
            entryMap[pathname] = fileName;
        }

    });

    return entryMap;
}
{
    ...
    entry: getEntry()
    ...
}

本demo采纳的是第二中写法,能够越发天真。

怎样明白entry point(bundle),chunk,module

在webpack中,怎样明白entry point(bundle),chunk,module?

依据图上的表述,我这里简单说一下便于明白的结论:

  • 设置中每一个文件比方index1.js,index2.js,detail.js,home.js都属于entry point.
  • entry这个设置中,每一个key值,index,detail,home都相当于chunk。
  • 我们在代码中的require或许import的都属于module,这点很好明白。
  • chunk的分类比较迥殊,有entry chunk,initial chunk,normal chunk,参考这个文章
  • 一般情况下,一个chunk对应一个output,在运用了CommonsChunkPlugin或许require.ensure以后,chunk就变成了initial chunk,normal chunk,这时候,一个chunk对应多个output。

明白这些观点关于后续运用webpack插件有很大的协助。

多进口页面html设置

之前我们设置HtmlWebpackPlugin时,一样采纳的是但页面的设置,这里我们将举行多页面革新,entryMap是上一步获得的entry:

function htmlAarray(entryMap) {
    let htmlAarray = [];

    Object.keys(entryMap).forEach(function(key){
        let fullPathName = path.resolve(pageDir, key);
        let fileName = path.resolve(fullPathName, key + '.html')
        if (fs.existsSync(fileName)) {
            htmlAarray.push(new HtmlWebpackPlugin({
                chunks: key, // 注重这里的key就是chunk
                filename: key + '.html',
                template: fileName,
                inlineSource:  '.(js|css)'
            }))
        }
    });

    return htmlAarray;

}
修正plugin设置:plugins: [
     ...
].concat(htmlMap)

模块热替代(Hot Module Replacement)

模块热替代 (Hot Module Replacement 或 HMR)是 webpack 供应的最有效的功用之一。它许可在运行时更新种种模块,而无需举行完整革新,很嵬峨上有木有!

下面说一下设置要领,它须要连系devServer运用:

devServer: {
    hot: true // 开启HMR
},

开启plugin:

const webpack = require('webpack');
plugins: [
    new webpack.NamedModulesPlugin(),
    new webpack.HotModuleReplacementPlugin(),
].concat(htmlMap)

连系React一同运用:

1.装置react-hot-loader

npm install react-hot-loader --save

并新建一个Container.jsx:

import React from 'react';
import Main from './Main.jsx';
import { hot } from 'react-hot-loader'

class Container extends React.Component {

    render() {
        return <Main />
    }
        
}
export default hot(module)(Container);

连系redux:假如项目没有运用redux,能够无需设置背面2步

2.修正store.js新增下面代码,为了让reducer也能及时热替代

if (module.hot) {
    module.hot.accept('./reducers/todoReducer.js', () => {
      const nextRootReducer = require('./reducers/todoReducer.js').default;
      store.replaceReducer(nextRootReducer);
    });
}

3.修正index.js

import ReactDom from 'react-dom';
import React from 'react';
import Container from './Main/Container.jsx';
import store from './store.js';

import { Provider } from 'react-redux';

ReactDom.render(
    <Provider store={store}>
        <Container />
    </Provider>
, document.getElementById('root'));

当掌握台看到[WDS] Hot Module Replacement enabled.代表开启胜利

运用ESLint

ESLint 是浩瀚 Javascript Linter 中的个中一种,其他比较罕见的另有 JSLintJSHint,之所以用 ESLint 是因为他能够自由挑选要运用哪些划定规矩,也有许多现成的 plugin 能够运用,别的他对 ES6 另有 JSX 的支撑水平跟其他 linter 相比之下也是最高的。

1.装置ESLint

npm install eslint eslint-loader babel-eslint --save

个中eslint-loader是将webpack和eslint连系起来在webpack的设置文件中新增一个eslint-loader种,修正以下:

{ test: /\.(js|jsx)$/, use: [{loader:'babel-loader'},{loader:'eslint-loader'}] ,include: path.resolve(srcRoot)},   


2.新建.eslintrc设置文件,将parser设置成babel-eslint

{
    "extends": ["eslint:recommended"],
    
    "parser": "babel-eslint",

    "globals": {
    },
    "rules": {
    }
} 

3.装置eslint-plugin-react:

npm install eslint-plugin-react --save
  • 申明一下,一般情况下每一个eslint划定规矩都是须要在rule下面设置,假如什么都不设置,实在自身eslint是不见效的。
  • eslint自身有许多默许的划定规矩模版,能够经由历程extends来设置,默许能够运用eslint:recommended。
  • 在运用react开辟时能够装置eslint-plugin-react来示知运用react专用的划定规矩来lint。

修正.eslintrc设置文件,增添rules,更多rules设置能够参考这里

{
    "extends": ["eslint:recommended","plugin:react/recommended"],
    
    "parser": "babel-eslint",

    "globals": {
        "window": true,
        "document": true,
        "module": true,
        "require": true
    },
    "rules": {
        "react/prop-types" : "off",
        "no-console" : "off"
    }
}

运用react-router

react-router壮大指出在于轻易代码治理,连系redux运用越发壮大,同时支撑web,native更多参考这里

1.装置react-router-dom

npm install react-router-dom --save

2.假如项目中用了redux,能够装置react-router-redux

npm install react-router-redux@next history --save

3.修正代码:

index.js

import ReactDom from 'react-dom';
import React from 'react';
import Container from './Main/Container.jsx';
import { store, history } from './store.js';

import { Provider } from 'react-redux';

import createHistory from 'history/createHashHistory';
import { ConnectedRouter } from 'react-router-redux';

const history = createHistory();

ReactDom.render(
    <Provider store={store}>
        <ConnectedRouter history={history}>
            <Container />
        </ConnectedRouter>
    </Provider>
, document.getElementById('root'));

连系history,react-router一共有3中差别的router:

  • BrowserRouter经由历程history/createBrowserHistory引入:当切换时,url会动态更新,底层运用的时html5的pushState
  • HashRouter经由历程history/createHashHistory引入:当切换时,动态修正hash,应用hashchange事宜。
  • MemoryRouter 经由历程history/createMemoryHistory引入:将途径,路由相干数据存入内存中,不触及url相干更新,兼容性好。

更多设置能够参考这里

4.假如想要在代码逻辑中猎取当前的route途径须要引入router-reducer:

新建main.js:

import { combineReducers } from 'redux';
import { routerReducer } from "react-router-redux";
import todoReducer from './todoReducer.js';

const reducers = combineReducers({
  todoReducer,
  router: routerReducer
});
export default reducers;

修正store.js:

import { createStore } from 'redux';
import mainReducer from './reducers/main.js';

const store = createStore(mainReducer);

export default store;

然后就能够在this.props.router内里猎取单相干的途径信息

5.假如须要自身经由历程action来触发router的跳转,须要引入routerMiddleware:

import { createStore,applyMiddleware } from 'redux';
import { routerMiddleware } from "react-router-redux";
const middleware = routerMiddleware(history);
const store = createStore(mainReducer,applyMiddleware(middleware));

6.运用Route和Link和withRouter:

先说说都是干吗的:

<Route exact path="/" component={Div1}></Route>
<Route path="/2" component={Div2}></Route>
export default withRouter(connect(
   state => ({
      todoList: state.todoReducer.todoList
   })
)(Main));

假如你在运用hash时碰到Warning: Hash history cannot PUSH the same path; a new entry will not be added to the history stack毛病,能够将push改成replace即:

<NavLink
    replace={true}
    to="/2"
    activeClassName="selected"
    >切换到2号</NavLink>

7.设置初始化路由:

BrowserRouter和HashRouter:

const history = createHistory();
history.push('2');

MemoryRouter:

const history = createMemoryHistory({
    initialEntries: ['/2']
});


运用redux-thunk

redux-thunk 是一个比较盛行的 redux 异步 action 中间件,比方 action 中有 setTimeout 或许经由历程 fetch通用长途 API 这些场景,那末久应当运用 redux-thunk 了。redux-thunk 协助你一致了异步和同步 action 的挪用体式格局,把异步历程放在 action 级别处理,对 component 没有影响。

1.装置redux-thunk:

npm install redux-thunk --save

2.修正store.js:

import { createStore,applyMiddleware } from 'redux';
import thunk from 'redux-thunk';
import mainReducer from './reducers/main';
...
const store = createStore(mainReducer, applyMiddleware(thunk));
...
export default store;

3.在action.js运用redux-thunk:

export const getData = (obj) => (dispatch, getState) => {
  setTimeout(()=>{
    dispatch({
        type: GET_DATA,
        obj: obj
    });
  },1000);
};

运用axios和async/await

axios 是一个基于Promise 用于浏览器和 nodejs 的 HTTP 客户端:

  • 从浏览器中竖立 XMLHttpRequest
  • 从 node.js 发出 http 要求
  • 支撑 Promise API
  • 自动转换JSON数据

1.装置axios:

npm install axios --save

2.在action中运用axios:

import axios from 'axios';
export const getData = (obj) => (dispatch, getState) => {
    axios.get('/json/comments.json').then((resp)=>{
        dispatch({
            type: GET_DATA,
            obj: resp
        });
    });
};

async/await:

Javascript的回调地狱,置信许多人都晓得,尤其是在node端,近年比较盛行的是Promise的处理方案,然则跟着 Node 7 的宣布,编程终级处理方案的 async/await回声而出。

function resolveAfter2Seconds() {
  return new Promise(resolve => {
    setTimeout(() => {
      resolve('resolved');
    }, 2000);
  });
}

async function asyncCall() {
  var result = await resolveAfter2Seconds();
}

asyncCall();

async/await的用处是简化运用 promises 异步挪用的操纵,并对一组 Promises实行某些操纵。await前提是要领返回的是一个Promise对象,正如Promises相似于构造化回调,async/await相似于组合天生器和 promises。

1.async/await须要装置babel-plugin-transform-async-to-generator

npm install babel-plugin-transform-async-to-generator --save

2.在.babelrc中增添设置:

"plugins": [
    "transform-async-to-generator"
]

如许做仅仅是将async转换generator,假如你当前的浏览器不支撑generator,你将会收到一个Uncaught ReferenceError: regeneratorRuntime is not defined的毛病,你须要:

3.装置babel-plugin-transform-runtime:

npm install babel-plugin-transform-async-to-generator --save

4.修正.babelrc中的设置(能够去掉之前设置的transform-async-to-generator):

"plugins": [
    "transform-runtime"
]

5.假如不想引入一切的polyfill(参考上面临babel的诠释),能够增添设置:

"plugins": [
    "transform-runtime",
        {
            "polyfill": false,

            "regenerator": true,
        }
]

6.连系axios运用

import axios from 'axios';
export const getData = (obj) => async (dispatch, getState) => {
    let resp = axios.get('/json/comments.json');
    dispatch({
        type: GET_DATA,
        obj: resp
    });
};

Code Splitting

1.关于webpack1,2之前,你能够运用require.ensure来掌握一个组件的懒加载:

require.ensure([], _require => {
    let Component = _require('./Component.jsx');
},'lazyname')

2.在webpack4中,官方已不再引荐运用require.ensure来运用懒加载功用Dynamic Imports,取而代之的是ES6的import()要领:

import(
  /* webpackChunkName: "my-chunk-name" */
  /* webpackMode: "lazy" */
  'module'
);

不小小视解释里的代码,webpack在打包时会动态辨认这里的代码来做相干的设置,比方chunk name等等。

3.Prefetching/Preloading modules:

webpack 4.6.0+支撑了Prefetching/Preloading的写法:

import(/* webpackPreload: true */ 'ChartingLibrary');

3.连系React-Router运用:

react-loadable对上述的功用做了封装,雄厚了一些功用,连系React-Router起来运用越发轻易。

npm install react-loadable --save

在react-router里运用:

function Loading() {
  return <div>Loading...</div>;
}

let Div2 = Loadable({
  loader: () => import('./Div2'), 
  loading: Loading,
});

<Route path="/2" component={Div2}></Route>

运用CommonsChunkPlugin

CommonsChunkPlugin 插件,是一个可选的用于竖立一个自力文件(又称作 chunk)的功用,这个文件包含多个进口 chunk 的大众模块。经由历程将大众模块拆出来,终究合成的文件能够在最最先的时刻加载一次,便存起来到缓存中供后续运用。

1.在webpack4之前的用法:

new webpack.optimize.CommonsChunkPlugin({
    name: 'common',
    chunks: ['page1','page2'],
    minChunks: 3
})
  • name: string: 提出出的称号
  • chunks: string[]: webpack会从传入的chunk内里提取大众代码,默许从一切entry里提取
  • minChunks: number|infinity|function(module,count)->boolean: 假如传入数字或infinity(默许值为3),就是通知webpack,只要当模块反复的次数大于即是该数字时,这个模块才会被提取出来。当传入为函数时,一切相符前提的chunk中的模块都会被传入该函数做盘算,返回true的模块会被提取到目的chunk。

更多的参数设置,能够参考这里

2.在webpack4以后的用法:

module.exports = {
  //...
  optimization: {
    splitChunks: {
      chunks: 'async',
      minSize: 30000,
      minChunks: 1,
      maxAsyncRequests: 5,
      maxInitialRequests: 3,
      automaticNameDelimiter: '~',
      name: true,
      cacheGroups: {
        vendors: {
          test: /[\\/]node_modules[\\/]/,
          priority: -10
        },
        default: {
          minChunks: 2,
          priority: -20,
          reuseExistingChunk: true
        }
      }
    }
  }
};
  • splitChunks: 设置一个星散chunk(替代老版本的CommonsChunkPlugin)
  • cacheGroups: 自定义设置重要运用它来决议天生的文件:
  • test: 限定局限
  • name: 天生文件名
  • priority: 优先级
  • minSize: number: 最小尺寸必需大于此值,默许30000B
  • minChunks: 其他entry援用次数大于此值,默许1
  • maxInitialRequests: entry文件要求的chunks不应当凌驾此值(要求过量,耗时)
  • maxAsyncRequests: 异步要求的chunks不应当凌驾此值
  • automaticNameDelimiter: 自动定名连接符
  • chunks: 值为”initial”, “async”(默许) 或 “all”:
  • initial: 进口chunk,关于异步导入的文件不处置惩罚
  • async: 异步chunk,只对异步导入的文件处置惩罚
  • all: 悉数chunk

你的点赞是我延续分享好东西的动力,迎接点赞!

交换

干货系列文章汇总以下,以为不错点个Star,迎接 加群 互相进修。

https://github.com/qq44924588…

我是小智,民众号「大迁天下」作者,对前端手艺坚持进修爱好者。我会常常分享自身所学所看的干货,在进阶的路上,共勉!

关注民众号,背景复兴福利,即可看到福利,你懂的。

《webpack4 中的最新 React百口桶实战运用设置指南!》

    原文作者:前端小智
    原文地址: https://segmentfault.com/a/1190000017048871
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞