Webpack4+Babel7+React16+Less簡單配置筆記

tyrocoder發表於2019-08-08

Webpack4+Babel7+React16+Less簡單配置筆記

一、專案初始化

新建一個專案react-init

mkdir react-init
cd react-init
複製程式碼

初始化

yarn init -y
# 或
npm init -y
複製程式碼

二、安裝Webpack

webpack4的安裝需要安裝兩個,一個是webpack,另外就是webpack-cli

yarn add webpack webpack-cli -D
# 或
npm i webpack webpack-cli -D
複製程式碼

三、建立webpack配置檔案

在專案根目錄下面建立config目錄,並在該目錄裡面建3個配置檔案,分別是:

webpack.base.conf.js —— 共有配置

webpack.dev.conf.js —— 開發環境配置

webpack.prod.conf.js —— 生產環境配置

因為使用了公共的配置項,所以為了能夠使用公共項,需要引入另外一個庫,安裝如下:

yarn add webpack-merge -D
# 或
npm i webpack-merge -D
複製程式碼

在webpack.base.conf.js裡面寫入:

const path = require('path');
const DIST_PATH = path.resolve(__dirname, '../dist');
const APP_PATH = path.resolve(__dirname, '../src');

module.exports = {
  entry: {
    app: APP_PATH+'/index.js'
  },
  output: {
    filename: "js/[name].[chunkhash].js",
    path: DIST_PATH
  },
  resolve: {
    extensions: [".js", ".jsx", ".less"],
    alias: {
      "@": APP_PATH
    }
  },
}
複製程式碼

在webpack.dev.conf.js裡面寫入:

const path = require("path");
const merge = require("webpack-merge");
const baseWebpackConfig = require("./webpack.base.conf");

module.exports = merge(baseWebpackConfig, {
  mode: "development",
  output: {
    filename: "js/[name].[hash:16].js"
  },
  devtool: "inline-source-map",
});
複製程式碼

在webpack.prod.conf.js裡面寫入:

const merge = require("webpack-merge");
const baseWebpackConfig = require("./webpack.base.conf");

module.exports = merge(baseWebpackConfig, {
  mode: "production",
});
複製程式碼

在根目錄下面建立src目錄,然後建立index.js檔案,作為整個專案的入口檔案,建立App.jsx檔案,作為react專案的根元件;

在根目錄下面建立public目錄,然後建立index.html檔案,作為整個單頁專案的模板檔案;

index.html內容如下:

<!DOCTYPE html>
<html lang="zh-cn">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <!-- <title><%= htmlWebpackPlugin.options.title %></title> -->
    <title>React-Init</title>
</head>
<body>
    <div id="root"></div>
</body>
</html>
複製程式碼

在package.json裡面,新增命令列指令碼:

"scripts": {
  "build": "webpack --config config/webpack.prod.conf.js"
 }
複製程式碼

四、安裝React

yarn add react react-dom
# 或
npm i react react-dom -S
複製程式碼

修改src/App.jsx檔案如下:

import React, { Component } from "react";

class App extends Component {
  render() {
    return (
      <h1>Hello React</h1>
    );
  }
}

export default App;
複製程式碼

修改src/index.js檔案如下:

import React from "react";
import ReactDom from "react-dom";

import App from "./App";

ReactDom.render(<App />, document.getElementById("root"));
複製程式碼

五、安裝Babel

為了使ES6的模組化被支援以及能夠轉為瀏覽器識別的ES5程式碼,和JSX格式解析,必須引入對應的babel和babel外掛,安裝如下:

yarn add babel-loader @babel/core @babel/preset-env @babel/preset-react -D
# 或
npm i babel-loader @babel/core @babel/preset-env @babel/preset-react -D
複製程式碼

配置babel:

在webpack.base.conf.js裡面

module.exports = {
  ...
  resolve: {
    extensions: [".js", ".jsx", ".less"],
    alias: {
      "@": APP_PATH
    }
  },
  // 以下是新增的內容
  module: {
    rules: [
      {
        test: /\.jsx?$/,
        use: 'babel-loader',
        include: APP_PATH
      },
    ]
  }
}
複製程式碼

然後在根目錄新建.babelrc檔案,內容如下:

{
  "presets": [
    "@babel/preset-env",
    "@babel/preset-react"
  ]
}
複製程式碼

六、新增Html模板

安裝html-webpack-plugin外掛:

yarn add html-webpack-plugin -D
# 或
npm i html-webpack-plugin -D
複製程式碼

這個可以將生成的JS檔案自動載入到html的script標籤內去,可以自定義html模板,具體看其在npm網站上的文件。

給webpack.prod.conf.js增加配置內容如下

...
const HtmlWebpackPlugin = require("html-webpack-plugin");

module.exports = merge(baseWebpackConfig, {
  mode: "production",
  plugins: [
    new HtmlWebpackPlugin({
      template: "public/index.html",
      minify: {
        removeComments: true,
        collapseWhitespace: true,
        removeAttributeQuotes: true
      }
    })
  ]
});
複製程式碼

此時,可以進行build了,執行

yarn build
# 或
npm run build
複製程式碼

如果沒有報錯,且根目錄下生成dist目錄,則表示之前的配置基本上正確了

webpack優化

生產過程中,可以使用clean-webpack-plugin對dist資料夾先進行清理:

yarn add clean-webpack-plugin -D
複製程式碼

然後在webpack.prod.conf.js裡面增加如下內容:

...
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
...
  plugins: [
    new CleanWebpackPlugin(),
    new HtmlWebpackPlugin({
      template: "public/index.html",
      minify: {
        removeComments: true,
        collapseWhitespace: true,
        removeAttributeQuotes: true
      }
    })
  ]
...
複製程式碼

七、新增熱載入開發環境

yarn add webpack-dev-server -D
複製程式碼

在webpack.dev.conf.js裡面新增:

...
const HtmlWebpackPlugin = require("html-webpack-plugin");
const webpack = require("webpack");

module.exports = merge(baseWebpackConfig, {
  ...
  plugins: [
    new HtmlWebpackPlugin({
      template: "public/index.html",
      inject: "body",
      minify: {
        html5: true
      },
      hash: false
    }),
    new webpack.HotModuleReplacementPlugin()
  ],
  devServer: {
    port: 3000,
    contentBase: path.join(__dirname, "../public"),
    compress: true,
    historyApiFallback: true,
    hot: true,
    https: false,
    noInfo: true,
    open: true,
    proxy: {}
  }
});
複製程式碼

然後在package.json的指令碼里面:

"scripts": {
  "build": "webpack --config config/webpack.prod.conf.js",
  "dev": "webpack-dev-server --inline --progress --config config/webpack.dev.conf.js"
}
複製程式碼

執行

yarn dev
# 或
npm run dev
複製程式碼

即可在開啟的瀏覽器裡面進行訪問,地址為localhost:3000

八、對CSS和Less處理

使用webpack我們可以在js裡面匯入css或less檔案,但是必須使用相應的loader才能進行處理。

yarn add css-loader mini-css-extract-plugin less less-loader postcss-loader autoprefixer -D
複製程式碼

在webpack.base.conf.js裡面新增

...
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
...
module.exports = {
  ...
  module: {
    rules: [
      {
        test: /\.jsx?$/,
        use: "babel-loader",
        include: APP_PATH
      },
      {
        test: /\.css$/,
        use: [
          MiniCssExtractPlugin.loader,
          {
            loader: "css-loader",
            options: {
              modules: true  // 使支援css modules
            }
          }
        ]
      },
      {
        test: /\.less$/,
        exclude: /node_modules/,
        use: [
          MiniCssExtractPlugin.loader,
          {
            loader: "css-loader",
            options: {
              modules: true
            }
          },
          {
            loader: "postcss-loader",
            options: {
              plugins: [require("autoprefixer")()]
            }
          },
          {
            loader: "less-loader",
            options: {
              modifyVars: {
                // 自定義的主題內容寫在這裡
              }
            }
          }
        ]
      },
    ]
  },
  plugins: [
    new MiniCssExtractPlugin({
      filename: "css/[name].[hash].css",
      ignoreOrder: false
    })
  ]
};
複製程式碼

為了使autoprefixer生效,需要在package.json裡面新增如下內容:

"browserslist": [
  "last 4 version",
  "> 1%",
  "maintained node versions",
  "not dead"
]
複製程式碼

九、對字型和圖片進行處理

安裝loader:

yarn add file-loader url-loader -D
複製程式碼

在webpack.base.conf.js裡面新增:

module.exports = {
  ...
  module: {
    rules: [
      ...
      {
        test: /\.(png|jpg|gif|jpeg|bmp|webp)$/,
        use: [
          {
            loader: "url-loader",
            options: {
              publicPath: "/",
              name: "images/[name].[ext]",
              limit: 512
            }
          }
        ]
      },
      {
        test: /\.(woff|svg|eot|woff2|tff)$/,
        use: "file-loader",
        exclude: /node_modules/
      }
    ]
  },
  ...
};
複製程式碼

到這裡,基本上所需要的配置都已經OK了,那麼全部的配置檔案內容如下所示:

  1. webpack.base.conf.js

    const path = require("path");
    const DIST_PATH = path.resolve(__dirname, "../dist");
    const APP_PATH = path.resolve(__dirname, "../src");
    const MiniCssExtractPlugin = require("mini-css-extract-plugin");
    
    module.exports = {
      entry: {
        app: APP_PATH + "/index.js"
      },
      output: {
        filename: "js/[name].[chunkhash].js",
        path: DIST_PATH
      },
      module: {
        rules: [
          {
            test: /\.jsx?$/,
            use: "babel-loader",
            include: APP_PATH
          },
          {
            test: /\.css$/,
            use: [
              MiniCssExtractPlugin.loader,
              {
                loader: "css-loader",
                options: {
                  modules: true
                }
              }
            ]
          },
          {
            test: /\.less$/,
            exclude: /node_modules/,
            use: [
              MiniCssExtractPlugin.loader,
              {
                loader: "css-loader",
                options: {
                  modules: true
                }
              },
              {
                loader: "postcss-loader",
                options: {
                  plugins: [require("autoprefixer")()]
                }
              },
              {
                loader: "less-loader",
                options: {
                  modifyVars: {
                    // 自定義的主題內容寫在這裡
                  }
                }
              }
            ]
          },
          {
            test: /\.(png|jpg|gif|jpeg|bmp|webp)$/,
            use: [
              {
                loader: "url-loader",
                options: {
                  publicPath: "/",
                  name: "images/[name].[ext]",
                  limit: 512
                }
              }
            ]
          },
          {
            test: /\.(woff|svg|eot|woff2|tff)$/,
            use: "file-loader",
            exclude: /node_modules/
          }
        ]
      },
      resolve: {
        extensions: [".js", ".jsx", ".less"],
        alias: {
          "@": APP_PATH
        }
      },
      plugins: [
        new MiniCssExtractPlugin({
          filename: "css/[name].[hash].css",
          ignoreOrder: false
        })
      ]
    };
    複製程式碼
  2. webpack.dev.conf.js

    const path = require("path");
    const merge = require("webpack-merge");
    const baseWebpackConfig = require("./webpack.base.conf");
    const HtmlWebpackPlugin = require("html-webpack-plugin");
    const webpack = require("webpack");
    
    module.exports = merge(baseWebpackConfig, {
      mode: "development",
      output: {
        filename: "js/[name].[hash:16].js"
      },
      devtool: "inline-source-map",
      plugins: [
        new HtmlWebpackPlugin({
          template: "public/index.html",
          inject: "body",
          minify: {
            html5: true
          },
          hash: false
        }),
        new webpack.HotModuleReplacementPlugin()
      ],
      devServer: {
        port: 3000,
        contentBase: path.join(__dirname, "../public"),
        compress: true,
        historyApiFallback: true,
        hot: true,
        https: false,
        noInfo: true,
        open: true,
        proxy: {}
      }
    });
    複製程式碼
  3. webpack.prod.conf.js

    const merge = require("webpack-merge");
    const baseWebpackConfig = require("./webpack.base.conf");
    const HtmlWebpackPlugin = require("html-webpack-plugin");
    const { CleanWebpackPlugin } = require("clean-webpack-plugin");
    
    module.exports = merge(baseWebpackConfig, {
      mode: "production",
      plugins: [
        new CleanWebpackPlugin(),
        new HtmlWebpackPlugin({
          template: "public/index.html",
          minify: {
            removeComments: true,
            collapseWhitespace: true,
            removeAttributeQuotes: true
          }
        })
      ]
    });
    複製程式碼
  4. .babelrc

    {
      "presets": ["@babel/preset-env", "@babel/preset-react"]
    }
    複製程式碼
  5. package.json

    {
      "name": "react-init",
      "version": "1.0.0",
      "main": "index.js",
      "license": "MIT",
      "scripts": {
        "build": "webpack --config config/webpack.prod.conf.js",
        "dev": "webpack-dev-server --inline --progress --config config/webpack.dev.conf.js"
      },
      "devDependencies": {
        "@babel/core": "^7.5.5",
        "@babel/plugin-transform-runtime": "^7.5.5",
        "@babel/preset-env": "^7.5.5",
        "@babel/preset-react": "^7.0.0",
        "autoprefixer": "^9.6.1",
        "babel-loader": "^8.0.6",
        "clean-webpack-plugin": "^3.0.0",
        "css-loader": "^3.2.0",
        "file-loader": "^4.2.0",
        "html-webpack-plugin": "^3.2.0",
        "less": "^3.9.0",
        "less-loader": "^5.0.0",
        "mini-css-extract-plugin": "^0.8.0",
        "postcss-loader": "^3.0.0",
        "url-loader": "^2.1.0",
        "webpack": "^4.39.1",
        "webpack-cli": "^3.3.6",
        "webpack-dev-server": "^3.7.2",
        "webpack-merge": "^4.2.1"
      },
      "dependencies": {
        "react": "^16.8.6",
        "react-dom": "^16.8.6"
      },
      "browserslist": [
        "last 4 version",
        "> 1%",
        "maintained node versions",
        "not dead"
      ]
    }
    複製程式碼

整個專案的目錄結構為:

react-init
├── config
│   ├── webpack.base.conf.js
│   ├── webpack.dev.conf.js
│   └── webpack.prod.conf.js
├── public
│   └── index.html
├── src
│   ├── App.jsx
│   ├── app.less
│   ├── assets
│   │   └── 01.jpeg
│   └── index.js
├── .babelrc
├── package.json
└── yarn.lock
複製程式碼

相關文章