【譯】如何從頭開始搭建React,Webpack4,Babel7工程
這是一篇非常適合新手的教程。
目錄:
- 你將會學習到的知識
- 建立專案
- 配置webpack
- 配置Babel
- 編寫React元件
- HTML webpack plugin
- webpack dev server
- 總結
你將會學習到的知識
- 如何安裝及配置webpack
- 如何安裝及配置Babel
- 如何安裝React
- 如何編寫React元件
- 如何在HTML頁面中引入打包檔案
- 如何安裝及配置webpack dev server
建立專案
首先,建立工程目錄:
mkdir webpack-react-tutorial && cd $_複製程式碼
建立工程的基礎目錄結構:
mkdir -p src複製程式碼
初始化專案:
npm init -y複製程式碼
配置webpack
webpack是一款非常強大的工具,學習webpack不僅可以用於搭建React專案,它適用於任何前端工程。
webpack提取原始的React元件,用於生成(幾乎)每個瀏覽器都能理解的JavaScript程式碼。
安裝webpack:
npm i webpack --save-dev複製程式碼
同時需要安裝webpack-cli:
npm i webpack-cli --save-dev複製程式碼
下一步,在 package.json
中新增webpack命令:
"scripts": { "build": "webpack --mode production" }複製程式碼
現在你不需要為webpack定義配置檔案。
老版本的webpack不會自動查詢配置檔案,但從webpack4開始,不需要配置檔案就可以直接進行開發。
接下來我將安裝並配置Babel來編譯我們的程式碼。
配置Babel
React元件大多是由ES6語法編寫。ES6是對語法的一次很好的改進,但老版本瀏覽器往往不能解析新的ES6語法。有狀態的React元件被生命為class,因此,為了讓ES6在舊版瀏覽器中執行,我們需要進行某種轉換。我們把這種轉換成為 編譯 。
webpack並不知道如何將ES6語法轉換為ES5,不過webpack可以使用 loader 來完成。即webpack載入器將一些東西作為輸入,並將其轉換為其他東西輸出。
webpack中的babel-loader便擔任著將ES6語法轉換為瀏覽器所能理解語法的工作。
- babel preset env 負責將ES6語法轉換成ES5
- babel preset react 負責將JSX語法轉化為JavaScript
安裝依賴:
npm i @babel/core babel-loader @babel/preset-env @babel/preset-react --save-dev複製程式碼
不要忘記配置Babel。在工程根目錄下建立 .babelrc
檔案,配置如下:
{ "presets": ["@babel/preset-env", "@babel/preset-react"] }複製程式碼
現在,我們需要編寫一個簡短的webpack配置檔案。
建立 webpack.config.js
檔案,配置如下:
module.exports = { module: { rules: [ { test: /\.(js|jsx)$/, exclude: /node_modules/, use: { loader: "babel-loader" } } ] } };複製程式碼
對於每個帶有js或jsx副檔名的檔案,Webpack通過babel-loader管理程式碼,將ES6轉換為ES5。
有了這個,我們就可以編寫React元件了。
編寫React元件
首先按照Container/Presentation原則,建立兩個React元件。
容器元件是承載所有邏輯的元件:用於處理狀態更改的函式,內部元件狀態等。 相反,展示元件僅用於展示。 展示元件是普通的JavaScript函式,它從容器元件接收資料作為props。
下面,我將構建一個簡單的帶文字框的React表單。
編寫程式碼之前,需要安裝React:
npm i react react-dom --save-dev複製程式碼
接著,建立元件的目錄結構:
mkdir -p src/js/components/{container,presentational}複製程式碼
下面我們建立容器元件,需滿足以下條件:
- 有自己的state
- 渲染出來是一個HTML表單
建立元件:
touch src/js/components/container/FormContainer.jsx複製程式碼
程式碼如下:
import React, { Component } from "react"; import ReactDOM from "react-dom"; class FormContainer extends Component { constructor() { super(); this.state = { title: "" }; } render() { return ( <form id="article-form"> </form> ); } } export default FormContainer;複製程式碼
這個元件目前沒有完成任何工作,它只是一個用於包含子元件的框架。
下面建立子元件:
touch src/js/components/presentational/Input.jsx複製程式碼
我們的展示元件是一個文字框。一個HTML文字框擁有以下屬性:
- type
- class
- id
- value
- required
所有的這些屬性都應該由父容器元件傳入子元件。
如果input擁有自己的state,在使用時一定要注意,確保HTML input是一個受控的React元件。
安裝如下依賴:
npm i prop-types --save-dev複製程式碼
回到React元件,展示組建程式碼如下:
import React from "react"; import PropTypes from "prop-types"; const Input = ({ label, text, type, id, value, handleChange }) => ( <div className="form-group"> <label htmlFor={label}>{text}</label> <input type={type} className="form-control" id={id} value={value} onChange={handleChange} required /> </div> ); Input.propTypes = { label: PropTypes.string.isRequired, text: PropTypes.string.isRequired, type: PropTypes.string.isRequired, id: PropTypes.string.isRequired, value: PropTypes.string.isRequired, handleChange: PropTypes.func.isRequired }; export default Input;複製程式碼
接下來,我們用容器元件包含這個展示組建:
import React, { Component } from "react"; import ReactDOM from "react-dom"; import Input from "../presentational/Input.jsx"; class FormContainer extends Component { constructor() { super(); this.state = { seo_title: "" }; this.handleChange = this.handleChange.bind(this); } handleChange(event) { this.setState({ [event.target.id]: event.target.value }); } render() { const { seo_title } = this.state; return ( <form id="article-form"> <Input text="SEO title" label="seo_title" type="text" id="seo_title" value={seo_title} handleChange={this.handleChange} /> </form> ); } } export default FormContainer;複製程式碼
webpack預設的入口檔案為 ./src/index.js
。我們建立這個檔案,並在入口檔案中引入容器元件 FormContainer
import FormContainer from "./js/components/container/FormContainer.jsx";複製程式碼
然後,我們就可以執行如下命令進行打包:
npm run build複製程式碼
打包後的js檔案在 ./dist/main.js
現在讓我們將實現將打包檔案引入HTML頁面。
HTML webpack plugin
要使React form展示出來,我們必須要讓webpack建立一個HTML頁面,並且將打包後的js檔案引入HTML。
Webpacks需要兩個額外的元件來處理HTML: html-webpack-plugin
和 html-loader
。
安裝依賴:
npm i html-webpack-plugin html-loader --save-dev複製程式碼
更新webpack配置檔案:
const HtmlWebPackPlugin = require("html-webpack-plugin"); module.exports = { module: { rules: [ { test: /\.(js|jsx)$/, exclude: /node_modules/, use: { loader: "babel-loader" } }, { test: /\.html$/, use: [ { loader: "html-loader" } ] } ] }, plugins: [ new HtmlWebPackPlugin({ template: "./src/index.html", filename: "./index.html" }) ] };複製程式碼
建立 ./src/index.html
檔案
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta.2/css/bootstrap.min.css" > <title>How to set up React, Webpack, and Babel</title> </head> <body> <div class="container"> <div class="row mt-5"> <div class="col-md-4 offset-md-1"> <p>Create a new article</p> <div id="create-article-form"> <!-- form --> </div> </div> </div> </div> </body> </html>複製程式碼
最後,將React元件掛在到id為 create-article-form
的元素上:
const wrapper = document.getElementById("create-article-form"); wrapper ? ReactDOM.render(<FormContainer />, wrapper) : false;複製程式碼
再次build:
npm run build複製程式碼
檢視 dist
目錄,你將會看到HTML結果檔案
使用webpack,不需要手動將js檔案引入HTML,打包後的檔案將會被自動注入。
開啟 ./dist/index.html
,你將會在瀏覽器中看到剛剛編寫的React表單
Webpack dev server
如果你不想每次改變檔案的時候都執行 npm run build
來檢視結果,使用簡單的三行配置就可以啟動本地的開發伺服器。配置後,webpack將在瀏覽器中啟動應用程式。 此外,每次修改後儲存檔案webpack伺服器都會自動重新整理瀏覽器的視窗。
安裝依賴:
npm i webpack-dev-server --save-dev複製程式碼
更新 package.json
:
"scripts": { "start": "webpack-dev-server --open --mode development", "build": "webpack --mode production" }複製程式碼
執行命令:
npm start複製程式碼
你將會在瀏覽器中看到如下介面:
並且,每次更新檔案webpack dev server都會自動重新整理頁面。
總結
create-react-app是一種開啟React專案的方法,幾乎所有東西都是開箱即用。但遲早,你都會想要調整或修改一下原有的webpack配置。
如果你學習瞭如何手動配置React,webpack和Babel,你就可以根據自己的需要從零開始配置React專案。
這些知識對於不需要完整的SPA但仍希望構建和分發ES6程式碼的情況也很有用。 通過組合webpack和Babel,可以將一堆React元件轉換為適合分發的bundle。
原文連結:https://www.valentinog.com/blog/react-webpack-babel/