Webpack 4+react+antd+axios+router 4+redux学習および足場構築_014


Webpack 4足場構築の学習
npmコマンド
パブリックnpmパッケージの初期化、パッケージング速度の向上
npm run dll 
   
yarn dll

開発環境
npm run dev
  
yarn dev

生産環境パッケージ
npm run build 
  
yarn build

インストールと初期化
まず公式の文書を添付します
githubアドレス
https://github.com/xiaopingzh...
不定期に更新されますが、役に立つと思ったら、スターを励ましてあげるといいです.
.
├── README.md
├── build
│   ├── webpack.dev.conf.js
│   ├── webpack.dll.conf.js
│   └── webpack.prod.conf.js
├── dist
├── dll
├── manifest.json
├── package-lock.json
├── package.json
├── public
│   ├── favicon.ico
│   └── index.html
├── src
│   ├── components
│   │   ├── Bread
│   │   │   └── Bread.js
│   │   └── SiderBar
│   │       └── SiderBar.js
│   ├── index.js
│   ├── layouts
│   │   └── BasicLayout.js
│   ├── pages
│   │   ├── Counter
│   │   │   └── Counter.js
│   │   └── Home
│   │       └── Home.js
│   ├── redux
│   │   ├── actions
│   │   │   └── counter.js
│   │   ├── reducer.js
│   │   ├── reducers
│   │   │   └── counter.js
│   │   └── store.js
│   ├── request
│   │   └── request.js
│   ├── router
│   │   └── Router.js
│   └── util
│       └── loadable.js
└── yarn.lock
  • 新規ディレクトリを作成しnpmを初期化し、webpackをローカルにインストールし、webpack-cli
  • を再インストールする.
    >npm init
    
    This utility will walk you through creating a package.json file.
    It only covers the most common items, and tries to guess sensible defaults.
    
    See `npm help json` for definitive documentation on these fields
    and exactly what they do.
    
    Use `npm install ` afterwards to install a package and
    save it as a dependency in the package.json file.
    
    Press ^C at any time to quit.
    package name: (webpack4)
    version: (1.0.0)
    description:
    entry point: (index.js)
    test command:
    git repository:
    keywords:
    author:
    license: (ISC)
    About to write to /Users/xiaopingzhang/UCloud/webpack4/package.json:
    
    {
      "name": "webpack4",
      "version": "1.0.0",
      "description": "",
      "main": "index.js",
      "scripts": {
        "test": "echo \"Error: no test specified\" && exit 1"
      },
      "author": "",
      "license": "ISC"
    }
    
    
    Is this OK? (yes) yes

    初期化後はプロンプトに従って一歩下がればいいので、その項目の説明などを入力できます.最初は大丈夫ですが、後で変更することもできます.
    次にwebpackをローカルにインストールし、webpack-cliを再インストールします.
    npm install webpack webpack-cli --save-dev

    ==--save-devはあなたが開発時に依存していたもので、--saveはあなたが発表した後も依存していたものです.==
    >npm install webpack webpack-cli --save-dev
    
    > [email protected] install /Users/xiaopingzhang/UCloud/webpack4/node_modules/fsevents
    > node install
    
    node-pre-gyp WARN Using needle for node-pre-gyp https download
    [fsevents] Success: "/Users/xiaopingzhang/UCloud/webpack4/node_modules/fsevents/lib/binding/Release/node-v57-darwin-x64/fse.node" is installed via remote
    
    > [email protected] postinstall /Users/xiaopingzhang/UCloud/webpack4/node_modules/webpack-cli
    > lightercollective
    
    
         *** Thank you for using webpack-cli! ***
    
    Please consider donating to our open collective
         to help us maintain this package.
    
      https://opencollective.com/webpack/donate
    
                        ***
    
    npm WARN [email protected] No description
    npm WARN [email protected] No repository field.
    
    + [email protected]
    + [email protected]
    added 458 packages from 239 contributors and audited 5208 packages in 18.624s
    found 0 vulnerabilities

    インストールが完了すると、インストールされているバージョンも表示されますが、一般的にインストールに問題はありません.インストールに失敗した場合は、グローバルインストールを試してみます.
    2.srcフォルダ、入口のjsファイル、htmlファイルを新規作成します.
    .
    ├── index.html
    ├── package.json
    └── src
        └── index.js

    index.jsファイル
    const component = () => {
      let element = document.createElement("div");
    
      element.innerHTML = "webpackworks";
    
      return element;
    };
    
    document.body.appendChild(component());
    
    

    index.html
    
    
      
        Start
      
    
      
        
      
    
    
    
    

    3.webpackでファイルをコンパイルすることを ぶ
    npx webpack
    >npx webpack
    
    Hash: 9ad2a368debc9967c1f4
    Version: webpack 4.29.0
    Time: 269ms
    Built at: 2019-01-27 21:15:22
      Asset      Size  Chunks             Chunk Names
    main.js  1.01 KiB       0  [emitted]  main
    Entrypoint main = main.js
    [0] ./src/index.js 218 bytes {0} [built]
    
    WARNING in configuration
    The 'mode' option has not been set, webpack will fallback to 'production' for this value. Set 'mode' option to 'development' or 'production' to enable defaults for each environment.
    You can also set it to 'none' to disable any default behavior. Learn more: https://webpack.js.org/concepts/mode/

    ブラウザでindex.htmlを き、Webページが に されているかどうかを します.
    Webpackは、エントリファイルindex.jsを した 、main.jsを する
    プロファイル
    1 の みにより、webpackの が に され、この はプロファイルによって するいくつかの が われる.
    babel
    Babelは、 の で されたJavaScriptコードを、 どこでも できるバージョンに にコンパイルします.このプロセスは「ソースコードからソースコードへ」コンパイルと ばれ、 コンパイルとも ばれます.
    npm install --save-dev babel-core babel-loader babel-preset-es2015 babel-preset-react babel-preset-stage-0

    しいbabelプロファイル.babelrc
    {
       "presets": [
         "es2015",
         "react",
         "stage-0"
       ],
       "plugins": []
    }
    //babel-core   Babel API    
    //babel-loader
    //babel-preset-es2015      ES6
    //babel-preset-react      JSX
    //babel-preset-stage-0      ES7   

    プロファイル
    webpack.base.conf.js
    
    webpack.dev.conf.js
    
    webpack.prod.conf.js

    それぞれ 、 、 である. のディレクトリ は
    .
    ├── build
    │   ├── webpack.base.conf.js
    │   ├── webpack.dev.conf.js
    │   └── webpack.prod.conf.js
    ├── dist
    │   └── main.js
    ├── index.html
    ├── package.json
    └── src
        └── index.js

    js/jsxファイルのロード
    npm install --save-dev babel-core babel-loader babel-preset-es2015 babel-preset-react babel-preset-stage-0

    srcディレクトリの に.babelrc
    {
      "presets": [
        [
          "env",
          {
            "targets": {
              "browsers": [">1%", "last 3 versions"]
            }
          }
        ],
        "stage-2",
        "latest",
        "react"
      ],
      "plugins": [
        "syntax-dynamic-import",
        "transform-class-properties",
        
        
        
        
        
        
            // "style": "css" //    
        
         
          antd     
      ]
    }
    
    

    ファイルの
        {
            test: /\.(js|jsx)$/,
            exclude: /(node_modules|bower_components)/, //  
            include: [
              path.resolve(__dirname, '../src')
            ], //  
            use: {
              loader: 'babel-loader'
            }
          },

    CSSファイルのロード
    npm install --save-dev style-loader css-loader

    プロファイルに
          {
            test: /\.css$/,
            use: ["style-loader", "css-loader"]
          }

    をロード
    npm install --save-dev url-loader file-loader

    プロファイルに
          {
            test: /\.(png|jpg|gif)$/,
            use: [
              {
                loader: "url-loader",
                options: {
                  limit: 8192
                }
              }
            ]
          }
    options limit:8192は、8 K のピクチャがbase 64 に され、HTMLに され、HTTP が することを する.
    ロードless
    ここで を んで、lessを り けてください.
    npm install --save-dev less-loader less

    antdデフォルトのトピック を するには、 でなければ する を すればいいです.
          {
            test: /\.less$/,
            use: [
              {
                loader: 'style-loader'
              },
              {
                loader: 'css-loader' // translates CSS into CommonJS
              },
              {
                loader: 'less-loader', // compiles Less to CSS
                options: {
                  modifyVars: {
                    'font-size-base': '12px',
                    'primary-color': '#0EA679'
                  },
                  javascriptEnabled: true
                }
              }
            ]
          }

    フォントの み み
    では、フォントのような のリソースはどのように されますか?file-loaderおよびurl-loaderは、 のファイルを してロードし、 ディレクトリに することができます.つまり、フォントを む のタイプのファイルに できます.Webpack.config.jsを してフォントファイルを します.
          {
            test: /\.(woff|woff2|eot|ttf|otf)$/,
            use: ["file-loader"]
          }

    HtmlWebpackPluginを
    HtmlWebpackPluginの は、HTMLテンプレートを することです.HtmlWebpackPluginはHTMLファイルの を し、あなたのwebpackパッケージにサービスを します.これは、ファイル にコンパイルするたびにハッシュが するwebpack bundleを めるのに に ちます.
    プラグインを してHTMLファイルを したり、lodashテンプレートを して のテンプレートを したり、 のloaderを してまずプラグインをインストールする があります.
    npm install --save-dev html-webpack-plugin

    プロファイルに
     plugins: [
        new HtmlWebpackPlugin({
          template: 'public/index.html',
          title: 'title', //   HTML title   
          favicon: 'public/favicon.ico',
          minify: {
            removeComments: true,
            collapseWhitespace: true,
            removeAttributeQuotes: true,
          },
        }),

    フォルダのクリーンアップ/dist
    するたびに/distフォルダをクリーンアップする.
    npm install clean-webpack-plugin --save-dev
    new CleanWebpackPlugin(['../dist'])

    モジュールの
    https://webpack.docschina.org...
    モジュールホットスワップ(Hot Module ReplacementまたはHMR)は、webpackが する も な の1つです. なリフレッシュを とせずに、 にさまざまなモジュールを できます.2つの があります
    1
  • package.json
  • "dev": "webpack --config build/webpack.dev.config.js --color --progress --hot"
  • index.js
  • import React from 'react';
    import ReactDom from 'react-dom';
    
    **if (module.hot) {
        module.hot.accept();
    }**
    //  
    

  • プロファイル
  • const webpack = require('webpack');
    
    devServer: {
        hot: true
    }
    
    plugins:[
         new webpack.HotModuleReplacementPlugin()
    ]
    

    redux
    https://www.redux.org.cn/
    を に して、 はこれが しいと っていたので、 き めたらできませんでした.
    ネット で を てみると、 がcodingをしているとあまり がありません.
    ここでは redux-thunkを しました
    npm install --save redux-thunk
    

    かれたコードを
    store
    の は、 で します.
    Debugコードを にするために、コンソールでreaduxログを します.
    // import { createStore, applyMiddleware } from 'redux';
    // import thunk from 'redux-thunk';
    
    // import rootReducer from './reducer';
    
    // const createStoreWithMiddleware = applyMiddleware(thunk)(createStore);
    // const store = createStoreWithMiddleware(rootReducer);
    
    // export default store;
    
    //       ,    ,        ,        。
    
    import thunk from "redux-thunk"; // redux                action     dispatch getState
    import { createLogger } from "redux-logger"; //   redux-logger    
    import { createStore, applyMiddleware } from "redux"; //   redux createStore、    compose
    import { composeWithDevTools } from "redux-devtools-extension"; // devToolsEnhancer,
    import reducer from "./reducer"; //   reducers  
    
    //          collapsed  action  ,     
    const loggerMiddleware = createLogger({ collapsed: true });
    
    //          
    const middleware = [thunk, loggerMiddleware];
    
    //   store
    const store = createStore(
      reducer,
      composeWithDevTools(applyMiddleware(...middleware))
    );
    
    export default store;
    

    action
    export const INCREMENT = 'counter/INCREMENT';
    export const DECREMENT = 'counter/DECREMENT';
    export const RESET = 'counter/RESET';
    
    export function increment() {
      return { type: INCREMENT };
    }
    
    export function decrement() {
      return { type: DECREMENT };
    }
    
    export function reset() {
      return { type: RESET };
    }

    reducer
    ページのreduceファイル
    import { INCREMENT, DECREMENT, RESET } from '../actions/counter';
    
    const initState = {
      count: 0,
    };
    
    export default function reducer(state = initState, action) {
      switch (action.type) {
        case INCREMENT:
          return {
            count: state.count + 1,
          };
        case DECREMENT:
          return {
            count: state.count - 1,
          };
        case RESET:
          return { count: 0 };
        default:
          return state;
      }
    }
    

    redecersはすべてのファイルのreducerを します
    import { combineReducers } from "redux";
    
    import counter from "./reducers/counter";
    
    export default combineReducers({
      counter
    });
    

    react-loadable
    https://github.com/jamiebuild...
    は に します
    //     
    import Loadable from 'react-loadable';
    import React, { Component } from 'react';
    import { Spin, Icon } from 'antd';
    
    const antIcon = ;
    const antLong = (
      
    );
    const antError = (
      
    );
    
    export const Loading = props => {
      if (props.error) {
        return (
          
        );
      } else if (props.timedOut) {
        return (
          
        );
      } else if (props.pastDelay) {
        return (
          
        );
      } else {
        return null;
      }
    };
    
    export const importPath = ({ loader }) => {
      return Loadable({
        loader,
        loading: Loading,
        delay: 200,
        timeout: 10000
      });
    };
    

    axiosはすべてのリクエストを にブロックし、データを します.
    な にこのファイルを すればOKです. を に いただけで、 で しましょう.axiosは に されています.
    import axios from "axios";
    import { message } from "antd";
    import NProgress from "nprogress";
    import "nprogress/nprogress.css";
    
    //           
    // Add a request interceptor
    axios.interceptors.request.use(
      config => {
        NProgress.start();
        return config;
      },
      error => {
        message.error("    ,   ");
        return Promise.reject(error);
      }
    );
    
    // Add a response interceptor
    axios.interceptors.response.use(
      response => {
        // NProgress.done();
        // if (response.data.RetCode === 101) {
        //   message.error(response.data.Message);
        //   return response;
        // }
        // if (response.data.RetCode === 100) {
        //   message.error(response.data.Message);
        //   return response;
        // }
        return response;
      },
      error => {
        message.error("    ,   ");
        NProgress.done();
        return Promise.reject(error);
      }
    );
    export default request;
    

    パブリックパス
    プラグインの
    
     plugins: [
        //   html
        new HtmlWebpackPlugin({
          template: 'public/index.html',
          path: '../public/index.html',
          inject: 'body',
          title: '    ',
          favicon: 'public/favicon.ico',
          filename: 'index.html',
          hash: true,
          minify: {
            html5: true,
            removeComments: true,
            collapseWhitespace: true,
            removeAttributeQuotes: true
          }
        }),
        new CleanWebpackPlugin(['../dist'], { allowExternal: true }),
        new BundleAnalyzerPlugin(),
        new MiniCssExtractPlugin({
          chunkFilename: '[chunkhash].css'
        }),
        new webpack.HashedModuleIdsPlugin(),
        new webpack.DllReferencePlugin({
          context: __dirname,
          manifest: require('../dll/manifest.json')
        }),
        new CopyWebpackPlugin([
          { from: 'dll/Dll.js', to: DIST_PATH }
        ])
      ]
    

    html-webpack-plugin
    const HtmlWebpackPlugin = require('html-webpack-plugin');
    
    new HtmlWebpackPlugin({
          template: 'public/index.html',
          path: '../public/index.html',
          inject: 'body',
          title: '    ',
          favicon: 'public/favicon.ico',
          filename: 'index.html',
          hash: true,
          minify: {
            html5: true,
            removeComments: true,
            collapseWhitespace: true,
            removeAttributeQuotes: true
          }
        }),

    copy-webpack-plugin
    
    const CopyWebpackPlugin = require('copy-webpack-plugin');
    
    new CopyWebpackPlugin([
          { from: 'dll/Dll.js', to: DIST_PATH }
        ])
    

    clean-webpack-plugin
    
    const CleanWebpackPlugin = require('clean-webpack-plugin');
    
    new CleanWebpackPlugin(['../dist'], { allowExternal: true })
    
    

    webpack-bundle-analyzer
    const BundleAnalyzerPlugin = require('webpack-bundle-analyzer')
      .BundleAnalyzerPlugin;
      
      new BundleAnalyzerPlugin(),
     

    mini-css-extract-plugin
    const MiniCssExtractPlugin = require('mini-css-extract-plugin');
    
     new MiniCssExtractPlugin({
          chunkFilename: '[chunkhash].css'
        })
        

    3つのプロファイルを
    webpack.dev.conf.js
    const path = require('path');
    const webpack = require('webpack');
    
    const HtmlWebpackPlugin = require('html-webpack-plugin');
    const CopyWebpackPlugin = require('copy-webpack-plugin');
    
    const DIST_PATH = path.resolve(__dirname, '../dist'); //    
    const APP_PATH = path.resolve(__dirname, '../src'); //     
    
    module.exports = {
      mode: 'development',
      entry: {
        index: './src/index.js'
      },
      output: {
        path: DIST_PATH, //    
        filename: 'index.js',
        chunkFilename: 'js/[name].[chunkhash].js', //      
        // publicPath: "./"
      },
      //      
      devtool: 'inline-source-map',
      //    
      module: {
        rules: [
          {
            test: /\.(js|jsx)$/,
            exclude: /(node_modules|bower_components)/, //  
            include: [
              path.resolve(__dirname, '../src'),
              path.resolve(__dirname, '../node_modules/antd/')
            ], //  
            use: {
              loader: 'babel-loader'
            }
          },
          {
            test: /\.css$/,
            use: ['style-loader', 'css-loader']
          },
          {
            test: /\.(png|jpg|gif)$/,
            use: [
              {
                loader: 'url-loader',
                options: {
                  limit: 8192
                }
              }
            ]
          },
          {
            test: /\.(woff|woff2|eot|ttf|otf)$/,
            use: ['file-loader']
          },
          //  antd    
          {
            test: /\.less$/,
            use: [
              {
                loader: 'style-loader'
              },
              {
                loader: 'css-loader' // translates CSS into CommonJS
              },
              {
                loader: 'less-loader', // compiles Less to CSS
                options: {
                  modifyVars: {
                    'font-size-base': '12px',
                    'primary-color': '#0EA679'
                  },
                  javascriptEnabled: true
                }
              }
            ]
          }
        ]
      },
      //  
      plugins: [
        new HtmlWebpackPlugin({
          template: 'public/index.html',
          path: '../public/index.html',
          inject: 'body',
          favicon: 'public/favicon.ico',
          title: '    ',
          overlay: true,
          minify: {
            html5: false
          },
          hash: true
        }),
        //    
        new webpack.HotModuleReplacementPlugin(),
        new webpack.HashedModuleIdsPlugin(),
        new webpack.DllReferencePlugin({
          context: __dirname,
          manifest: require('../dll/manifest.json')
        }),
        new CopyWebpackPlugin([
          { from: 'dll/Dll.js', to: DIST_PATH }
        ])
      ],
      //    
      devServer: {
        port: '3300',
        contentBase: DIST_PATH,
        historyApiFallback: true,
        hot: true, //   
        https: false,
        compress: false,
        noInfo: true,
        open: true,
        proxy: {
          // '/': {
          //   target: '',
          //   changeOrigin: true,
          //   secure: false,
          // },
        }
      }
    };
    

    webpack.dll.conf.js
    const path = require('path');
    const webpack = require('webpack');
    const CleanWebpackPlugin = require('clean-webpack-plugin');
    
    const vendors = [
      'antd',
      'axios',
      'nprogress',
      'react',
      'react-dom',
      'react-loadable',
      'react-redux',
      'react-router',
      'react-router-dom',
      'redux'
    ];
    
    module.exports = {
      entry: {
        vendor: vendors
      },
      output: {
        path: path.resolve(__dirname, '../dll'),
        filename: 'Dll.js',
        library: '[name]_[hash]'
      },
      plugins: [
        new webpack.DllPlugin({
          path: path.resolve(__dirname, '../dll', 'manifest.json'),
          name: '[name]_[hash]',
          context: __dirname
        }),
        new CleanWebpackPlugin(['../dll'], { allowExternal: true })
      ]
    };
    

    webpack.prod.conf.js
    
    const path = require('path');
    const webpack = require('webpack');
    
    const CopyWebpackPlugin = require('copy-webpack-plugin');
    const CleanWebpackPlugin = require('clean-webpack-plugin');
    const HtmlWebpackPlugin = require('html-webpack-plugin');
    const MiniCssExtractPlugin = require('mini-css-extract-plugin');
    const BundleAnalyzerPlugin = require('webpack-bundle-analyzer')
      .BundleAnalyzerPlugin;
    
    const DIST_PATH = path.resolve(__dirname, '../dist'); //    
    
    module.exports = {
      mode: 'production',
      entry: {
        index: './src/index.js'
      },
      output: {
        path: DIST_PATH, //    
        filename: 'index.js',
        chunkFilename: '[name]_[hash].js', //      
        // publicPath: './'
      },
      //      
      devtool: 'source-map',
      //    
      module: {
        rules: [
          {
            test: /\.(js|jsx)$/,
            exclude: /(node_modules|bower_components)/, //  
            include: [
              path.resolve(__dirname, '../src'),
              path.resolve(__dirname, '../node_modules/antd/')
            ], //  
            use: {
              loader: 'babel-loader'
            }
          },
          {
            test: /\.css$/,
            use: ['style-loader', 'css-loader']
          },
          {
            test: /\.(png|jpg|gif)$/,
            use: [
              {
                loader: 'url-loader',
                options: {
                  limit: 8192
                }
              }
            ]
          },
          //  antd    
          {
            test: /\.less$/,
            use: [
              {
                loader: 'style-loader'
              },
              {
                loader: 'css-loader' // translates CSS into CommonJS
              },
              {
                loader: 'less-loader', // compiles Less to CSS
                options: {
                  minimize: true,
                  modifyVars: {
                    'font-size-base': '12px',
                    'primary-color': '#0EA679'
                  },
                  javascriptEnabled: true
                }
              }
            ]
          },
          {
            test: /\.(woff|woff2|eot|ttf|otf)$/,
            use: ['file-loader']
          }
        ]
      },
      //  
      plugins: [
        //   html
        new HtmlWebpackPlugin({
          template: 'public/index.html',
          path: '../public/index.html',
          inject: 'body',
          title: '    ',
          favicon: 'public/favicon.ico',
          filename: 'index.html',
          hash: true,
          minify: {
            html5: true,
            removeComments: true,
            collapseWhitespace: true,
            removeAttributeQuotes: true
          }
        }),
        new CleanWebpackPlugin(['../dist'], { allowExternal: true }),
        new BundleAnalyzerPlugin(),
        new MiniCssExtractPlugin({
          chunkFilename: '[chunkhash].css'
        }),
        new webpack.HashedModuleIdsPlugin(),
        new webpack.DllReferencePlugin({
          context: __dirname,
          manifest: require('../dll/manifest.json')
        }),
        new CopyWebpackPlugin([
          { from: 'dll/Dll.js', to: DIST_PATH }
        ])
      ]
      //    
    };
    

    の み み
    パッケージエラー
    ERROR in Path must be a string. Received undefined
    Child html-webpack-plugin for "index.html":
         1 asset
        Entrypoint undefined = index.html
        

    このエラーはパッケージ に しません.バージョンの が であるはずです.
    https://github.com/jantimon/h...
    き わってやっと を れたことに づいて、 を します.
    の で、 の なブログやgithub、ドキュメントも にしました.
    https://github.com/brickspert...
    https://github.com/NewPrototy...
    https://github.com/axios/axios
    https://github.com/jamiebuild...
    https://www.webpackjs.com/con...