玩轉webpack——從零配置一個react項目

近來得閒,從新擼了一邊webpack文檔,將webpack的用法以及做用基本理清了脈絡,雖然各大前端框架的生態系統愈來愈完善,每一個框架基本都搭配了一套標準的腳手架工具,可是那是搭配好的套餐,用起來雖然也還行,仍是總以爲哪裏不得勁兒,就像開車開了個自動檔模式,不能根據本身的項目爲所欲爲的搭配功能。因此今天咱們就來好好啃一啃webpack,知其然也知其因此然。css

核心概念

webpack的核心功能就是模塊化打包,既然是打包就必定涉及到entry(入口)和output(出口),剩下的兩個核心概念是loader(加載器)和plugin(插件)以及mode(模式)。html

entry && output

entry和output就是字面意思上的入口和出口,就是打包過程中讀取代碼的入口以及編譯輸出文件。前端

mode

mode有點相似於半自動擋模式:提供mode配置選項,webpack會使用相應模式的內置功能進行自動優化。就這麼一句話就能夠歸納了模式。至於在哪一種模式下,webpack會開啓那些功能,能夠看以下表:node

選項 描述
development 會將 process.env.NODE_ENV 的值設爲 development。啓用 NamedChunksPlugin 和 NamedModulesPlugin。
production 會將 process.env.NODE_ENV 的值設爲 production。啓用 FlagDependencyUsagePlugin, FlagIncludedChunksPlugin, ModuleConcatenationPlugin, NoEmitOnErrorsPlugin, OccurrenceOrderPlugin, SideEffectsFlagPlugin 和 UglifyJsPlugin.

loader

loader是加載器,用於對模塊的源代碼進行轉換。loader 能夠將全部類型的文件轉換爲 webpack 可以處理的有效模塊,而後你就能夠利用 webpack 的打包能力,對它們進行處理。react

在 webpack 的配置中 loader 有兩個目標:webpack

  1. test 屬性,用於標識出應該被對應的 loader 進行轉換的某個或某些文件。
  2. use 屬性,表示進行轉換時,應該使用哪一個 loader。
const config = {
  module: {
    rules: [
      { test: /\.txt$/, use: 'raw-loader' }
    ]
  },
};
複製代碼

以上配置中,對一個單獨的 module 對象定義了 rules 屬性,裏面包含兩個必須屬性:test 和 use。這告訴 webpack 編譯器(compiler) 以下信息:git

「嘿,webpack 編譯器,當你碰到「在 require()/import 語句中被解析爲 '.txt' 的路徑」時,在你對它打包以前,先使用 raw-loader 轉換一下。」github

當你須要對各個文件轉爲webpack可以處理的有效模塊時能夠去loader列表選擇一個合適的加載器web

plugin

插件則能夠用於執行範圍更廣的任務。插件的範圍包括,從打包優化和壓縮,一直到從新定義環境中的變量。插件接口功能極其強大,能夠用來處理各類各樣的任務。 想要使用一個插件,你只須要 require() 它,而後把它添加到 plugins 數組中。多數插件能夠經過選項(option)自定義。你也能夠在一個配置文件中由於不一樣目的而屢次使用同一個插件,這時須要經過使用 new 操做符來建立它的一個實例。 當你想用某些實現某些任務優化時能夠去插件列表看沒有現成的插件開箱即用,npm

這裏有個例子能夠說明loader以及plugin用法

const HtmlWebpackPlugin = require('html-webpack-plugin'); // 經過 npm 安裝
const webpack = require('webpack'); // 用於訪問內置插件

const config = {
    ...
    plugins: [
        new HtmlWebpackPlugin({template: './src/index.html'})
    ]
};

module.exports = config;
複製代碼

引入了HtmlWebpackPlugin插件自動生成一個HTML文件。

配置文件

雖然webpack支持在命令行中手動敲下webpack-cli命中以構建文件,可是通常的項目要複雜的多, 因此webpack支持提供配置文件。這比在終端(terminal)中手動輸入大量命令要高效的多。因此讓咱們建立一個取代以上使用 CLI 選項方式的配置文件:

const path = require('path');

module.exports = {
  entry: './src/index.js',
  output: {
    filename: 'bundle.js',
    path: path.resolve(__dirname, 'dist')
  }
};
複製代碼

這是一個最簡單的配置文件,定義了輸入文件與輸出文件,讀取並運行src下的index.js文件將生成的bundle.js輸出到dist文件夾中。 有了這樣的一個配置文件以後,有兩中方式啓動它

  1. 經過命令行工具運行npx webpack --config webpack.config.js 這行命令表示以指定的webpack配置文件運行webpack命令

若是 webpack.config.js 存在,則 webpack 命令將默認選擇使用它。咱們在這裏使用 --config 選項只是向你代表,能夠傳遞任何名稱的配置文件。這對於須要拆分紅多個文件的複雜配置是很是有用。

  1. NPM 腳本(NPM Scripts) 考慮到用 CLI 這種方式來運行本地的 webpack 不是特別方便,咱們能夠設置一個快捷方式。在 package.json 添加一個 npm 腳本(npm script):
"scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "build": "webpack"
},
複製代碼

如今,可使用 npm run build 命令,來替代咱們以前使用的 npx 命令。

談談我本身對webpack的理解,把webpack看做是要編織一條美麗的珍珠項鍊的話,那麼配置文件則是項鍊的鏈子,而webpack中loader列表插件列表則至關於原料庫,咱們能夠從原料庫中挑出咱們所須要的珍珠,entry和output則是選擇以及打磨這條項鍊的入口及出口。好了一切準備就緒了,咱們要學習的變成如何打造一條美麗的珍珠項鍊。首先是要學習如何打磨完美的入口和出口。而後咱們要學習應該在什麼地方放上怎樣的珠子,以及如何放上去。

實例——從零建立一個React應用

如今咱們能夠從簡單到複雜一步一步來完成一個針對react的從0到1的配置文件:

實現流程

1,初始化npm項目,生成package.json。

2,添加public/index.html。

3, 安裝Babel,建立.babelrc進行配置。

4,安裝react、react-dom、熱更新react-hot-loader。

5,安裝webpack,建立webpack.config.js進行配置。

6,添加src/index.js、src/App.js、src/App.css。

7,配置package.json,修改啓動命令。

8,啓動項目

具體步驟

1. 初始化npm項目,生成package.json

建立一個新項目,並cd進入。

$ mkdir webpack-demo
$ cd webpack-demo
複製代碼

建立package.json文件, 若是你想跳過初始化時的問題,加上 -y,以默認選項安裝:

npm init -y
複製代碼

2. 添加public/index.html。

mkdir public
cd public
touch index.html
複製代碼

index.html

<!-- sourced from https://raw.githubusercontent.com/reactjs/reactjs.org/master/static/html/single-file-example.html -->
<!DOCTYPE html>
<html>

<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
  <title>React Starter</title>
</head>

<body>
  <div id="root"></div>
  <noscript>
    You need to enable JavaScript to run this app.
  </noscript>
  <script src="../dist/bundle.js"></script>
</body>
</html>
複製代碼

這裏引入的bundle.js後面會用到。

3. 安裝Babel,建立.babelrc進行配置。

cd ../
npm install -D @babel/core@7.1.0 @babel/cli@7.1.0 @babel/preset-env@7.1.0 @babel/preset-react@7.0.0
touch .babelrc

複製代碼

.babelrc

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

4. 安裝react、react-dom、熱更新react-hot-loader

npm i react react-dom -S
npm i react-hot-loader -D

複製代碼

5. 咱們須要安裝webpack的以及須要的開發依賴,建立webpack.config.js進行配置

npm i webpack webpack-cli webpack-dev-server style-loader css-loader babel-loader --save-dev
touch webpack.config.js
複製代碼

webpack.config.js

const path = require("path");
const webpack = require("webpack");

module.exports = {
  entry: "./src/index.js",
  mode: "development",
  module: {
    rules: [
      {
        test: /\.(js|jsx)$/,
        exclude: /(node_modules|bower_components)/,
        loader: "babel-loader",
        options: { presets: ["@babel/env"] }
      },
      {
        test: /\.css$/,
        use: ["style-loader", "css-loader"]
      }
    ]
  },
  resolve: { extensions: ["*", ".js", ".jsx"] },
  output: {
    path: path.resolve(__dirname, "dist/"),
    publicPath: "/dist/",
    filename: "bundle.js"
  },
  devServer: {
    contentBase: path.join(__dirname, "public/"),
    port: 3000,
    publicPath: "http://localhost:3000/dist/",
    hotOnly: true
  },
  plugins: [new webpack.HotModuleReplacementPlugin()]
};
複製代碼

6. 添加src/index.js、src/App.js、src/App.css。

mkdir src
cd src
touch index.js
touch App.js
touch App.css
複製代碼

index.js

import React from "react";
import ReactDOM from "react-dom";
import App from "./App.js";
ReactDOM.render(<App />, document.getElementById("root"));
複製代碼

App.js

import React, { Component} from "react";
import {hot} from 'react-hot-loader';
import "./App.css";

class App extends Component{
  render(){
    return(
      <div className="App">
        <h1> Hello</h1>
      </div>
    );
  }
}

export default hot(module)(App);
複製代碼

App.css

.App {
  margin: 1rem;
  font-family: Arial, Helvetica, sans-serif;
  border: 1px solid red;
}
複製代碼

7. 配置package.json,修改啓動命令。

在package.json裏配置scripts字段。

"scripts": {
    "start": "webpack-dev-server --mode development",
    "test": "echo \"Error: no test specified\" && exit 1"
  }
複製代碼

8. 啓動項目。

npm start
複製代碼

在瀏覽器鍵入http://localhost:3000以啓動項目

Github地址

相關文章
相關標籤/搜索