使用Webpack4 搭建React項目

使用Webpack 搭建React項目的方法和步驟

參考文章:《How to Create a React app from scratch using Webpack 4 》 write by Linh Nguyen Mycss

建立項目以及使用webpack編譯項目

  1. 使用npm init新建功能,若是想要跳過各類詢問,可使用 -y命令:
npm init -y
  1. 接下來要使用webpack做爲開發的依賴項,以及webpack-cli, 它可讓咱們在命令行中使用webpack, 使用如下命令來安裝:
npm i webpack webpack-cli -D

命令解釋html

  • i:install
  • -D: --dave-dev

以上命令等同於node

npm install webpack webpack-cli --save-dev
  1. 建立一個src文件夾並在文件夾下建立index.js, 將如下示例代碼寫入index.js:
console.log("hello");
  1. 如今,修改package.json, 添加scripts中2條命令start 和 build,代碼以下:
{
    "name": "translation-tool-webpack-react",
    "version": "1.0.0",
    "description": "",
    "main": "index.js",
    "scripts": {
        "start": "webpack --mode development",
        "build": "webpack --mode production"
    },
    "keywords": [],
    "author": "",
    "license": "ISC",
    "devDependencies": {
        "webpack": "^4.41.2",
        "webpack-cli": "^3.3.10"
    }
}

Webpack4 如今有2中模式,development和production, 當運行
npm run start或者 npm start 的時候,會在dist文件夾下建立一個main.js, 會包含咱們寫在src中的代碼,效果如圖:
imgreact

若是運行npm run build 那麼輸出的代碼如圖所示
imgwebpack

設置React 和 Babel

若是想要使用React來進行編碼,須要使用Babel, 它會將ES6轉換成ES5,由於目前並非全部的瀏覽器都支持ES6,例如IEweb

  1. 安裝react 和 react-dom做爲依賴
npm i react react-dom -S

命令解釋npm

  • -S: --save
  1. 安裝babel-core, babel-loader, babel-preset-env, babel-preset-react做爲開發依賴項 注意此處的版本問題,babel-core6 和babel-loader8不兼容,須要使用babel-core6和babel-loader7,原文中沒有提到這個問題
npm i babel-core babel-loader@7 babel-preset-env, babel-preset-react -D

命令解釋json

  • babel-core 將ES6代碼轉換成ES5
  • babel-loader: 在使用webpack配置Babel時,babel-loader幫助轉換JavaScript的依賴項,例如當你導入本身開發的components到其餘components中時
  • babel-preset-env: 根據須要支持的瀏覽器,決定哪些轉換(transformations)和插件(plugins)以及墊片(polyfills)被使用
  • babel-preset-react: 全部React插件的預調裝置(preset),例如將JSX轉換爲函數(functions)
  1. 建立webpack.config.js爲babel-loader設置規則
module.exports = {
    module: {
        rules: [
            {
                test: /\.js$/,
                exclude: /node_modules/,
                use: {
                    loader: "babel-loader"
                }
            }
        ]
    }
}
  1. 而後須要建立一個獨立的文件 .babelrc 提供babel-loader的一些選項。 這些能夠在webpack.config.js文件中寫,可是更多經驗表名,獨立出來會更好,一是可讀性會更好,二是非webpack類的配置工具也能夠複用。 配置內容以下:
{
    "preset": ["env", "react"]
}
  1. 接下來,修改index.js的內容來加載一個component:
import React from 'react';
import ReactDOM from 'react-dom';

const Index = () => {
    return <div>Hello React!</div>
};

ReactDOM.render(<Index />, document.getElementById("index));
  1. 同時也須要在src文件夾下建立一個index.html文件做爲加載React組件的模板
<!DOCTYPE html>
<html lang="en">
<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>React and Webpack4</title>
</head>
<body>
  <section id="index"></section>
</body>
</html>
  1. 安裝html-webpack-plugin並在webpack.confg.js中配置它。 這個插件會生成一個html網頁,插入一個<script>,將文件生成在dist/index.html並輕量化。數組

    • 安裝html-webpack-plugin做爲開發以來
    npm i html-webpack-plugin -D
    • 更新webpack 配置文件:
    const HtmlWebPackPlugin = require("html-webpack-plugin");
    
    const htmlPlugin = new HtmlWebPackPlugin({
    template: "./src/index.html",
    filename: "./index.html"
    });
    
    module.exports = {
    module: {
        rules: [
        {
            test: /\.js$/,
            exclude: /node_modules/,
            use: {
            loader: "babel-loader"
            }
        }
        ]
    },
    plugins: [htmlPlugin]
    };

    plugin的配置也能夠寫在module裏面:
    plugins: [ new HtmlWebPackPlugin({ template: "./src/index.html", filename: "./index.html" }); ]
    可是更推薦第一種,這樣可讀性比較好。瀏覽器

    template的值是生成html文件時的模板html文件。 此時運行命令npm run start或者npm start, 能夠看到index.html生成:
    img
    此時打開dist下的index.html文件,會看到瀏覽器中顯示"Hello React"。

設置webpack-dev-server

每次修改後須要從新編譯再看效果是很麻煩的事情,所以,咱們可使用webpack-dev-server模塊來讓webpack監聽代碼的改動,並及時更新組件

安裝webpack-dev-server做爲開發依賴

npm i webpack-dev-server -D

而後修改package.json的start命令,以下面所示:

{
    "name": "translation-tool-webpack-react",
    "version": "1.0.0",
    "description": "",
    "main": "index.js",
    "scripts": {
        "start": "webpack-dev-server --mode development --open --hot",
        "build": "webpack --mode production"
    },
    "keywords": [],
    "author": "",
    "license": "ISC",
    "devDependencies": {
        "babel-core": "^6.26.3",
        "babel-loader": "^7.1.5",
        "babel-preset-env": "^1.7.0",
        "babel-preset-react": "^6.24.1",
        "css-loader": "^3.2.0",
        "html-webpack-plugin": "^3.2.0",
        "style-loader": "^1.0.0",
        "webpack": "^4.41.2",
        "webpack-cli": "^3.3.10",
        "webpack-dev-server": "^3.9.0"
    },
    "dependencies": {
        "react": "^16.11.0",
        "react-dom": "^16.11.0"
    }
}

如今運行npm run start 或者npm start命令,會自動打開瀏覽器並打開頁面localhonst:8080 (--open 命令的效果),如今頁面會根據代碼的變更熱加載。 若是不想每次變動整個頁面,只變動有變化的組件,可使用--hot命令(詳情參考Hot Module Replacement

設置CSS

當咱們在React組件中導入css文件時,會須要css-loader來加載它們。當css加載完畢,還須要style-loader來將它們插入到咱們的DOM中:添加一個<style>標籤到HTML頁面<head>

  1. 安裝這兩個模塊
npm i css-loader style-loader -D

2.更新webpack.config.js:

const HtmlWebPackPlugin = require("html-webpack-plugin");

const htmlWebpackPlugin = new HtmlWebPackPlugin({
  template: "./src/index.html",
  filename: "./index.html"
});

module.exports = {
  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        use: {
          loader: "babel-loader"
        }
      },
      {
        test: /\.css$/,
        use: ["style-loader", "css-loader"]
      }
    ]
  },
  plugins: [htmlWebpackPlugin]
};

注意這裏的loader的添加順序。 咱們須要先解析CSS文件,而後在用style-loader加載到DOM。 默認狀況下,webpack是從右到左(從數組的最後一位向第一位)加載

CSS 模塊化

使用webpack能夠將css模塊化,即加載的class name會被限制在使用的組件中,從而限制其做用範圍。

  1. 給css-loader添加一些配置:
const HtmlWebPackPlugin = require("html-webpack-plugin");

const htmlWebpackPlugin = new HtmlWebPackPlugin({
  template: "./src/index.html",
  filename: "./index.html"
});

module.exports = {
  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        use: {
          loader: "babel-loader"
        }
      },
      {
        test: /\.css$/,
        use: [
          {
            loader: "style-loader"
          },
          {
            loader: "css-loader",
            options: {
              modules: true,
              importLoaders: 1,
              localIdentName: "[name]_[local]_[hash:base64]",
              sourceMap: true,
              minimize: true
            }
          }
        ]
      }
    ]
  },
  plugins: [htmlWebpackPlugin]
};

咱們在設置配置的時候,每一個loader都變成了一個對象,option配置的解釋:

  • module: true 開啓CSS模塊化
  • importLoaders 設置css-loader前還有多少loader被加載,例如,sass-loader應該在css-loader前加載
  • localIdentName 能夠配置生成的class name:
    • [name] 會取所在的component的名字
    • [local] class 或者id的取值
    • [hash:base64] 每一個component的css隨機生成的惟一哈希值

有了模塊化,咱們就不用擔憂同一個class name在整個項目中衝突的問題,只須要考慮同一個component中如何定義class name便可。

解決import時後綴名的問題

配置webpack的resolve,能夠定義加載文件的規則,例如,不想每次導入的時候都精確到文件以及後綴名,能夠修改webpack.config.js以下:

const HtmlWebPackPlugin = require("html-webpack-plugin");
const htmlPlugin = new HtmlWebPackPlugin({
    template: "./src/index.html",
    filename: "./index.html"
})

module.exports = {
    module: {
        rules: [{
                test: /\.js$/,
                exclude: /node_modules/,
                use: {
                    loader: 'babel-loader'
                }
            },
            {
                test: /\.jsx$/,
                exclude: /node_modules/,
                use: {
                    loader: 'babel-loader'
                }
            },
            {
                test: /\css$/,
                use: [{
                        loader: "style-loader",
                    },
                    {
                        loader: "css-loader",
                        options: {
                            modules: true,
                            importLoaders: 1,
                            localIdentName: "[name]_[local]_[hash:base64]",
                            sourceMap: true,
                            minimize: true
                        }
                    }
                ]
            }
        ]
    },
    plugins: [htmlPlugin],
    resolve: { 
        extensions: ['.js', '.jsx', '.json'] 
}
相關文章
相關標籤/搜索