【译】如何从头开始搭建React,Webpack4,Babel7工程
栏目: JavaScript · 发布时间: 5年前
内容简介:这是一篇非常适合新手的教程。目录:
这是一篇非常适合新手的教程。
目录:
- 你将会学习到的知识
- 建立项目
- 配置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/
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。