如何使用Webpack4和Babel7设置React
介绍
学习 React 的一种常用方法是使用 create-react-app,这是一种引导任何 React 项目的轻量级方法。 但为了达到特定目的,有时需要从头开始配置您的应用程序。 在本教程中,我们将使用 Webpack 和 Babel 设置 React。
第 1 步 — 设置项目
在开始之前,请确保在您的机器上安装了编辑器和终端。 此外,您还需要安装了带有 npm 的 Node.js 版本。 在继续阅读之前,请确保已完成所有设置。
在我们开始编写任何代码之前,让我们创建一个新目录来存放我们的项目。 在您计算机上的任何位置,在终端中运行以下命令:
mkdir webpack-babel-react-starter cd webpack-babel-react-starter
我们需要使用 package.json 文件初始化我们的项目,因为我们将安装一些对设置至关重要的包。 运行以下命令:
yarn init -y
注意: 在本教程中,我们将使用 yarn 作为我们的包管理器。 如果您使用的是 npm,请确保运行相应的命令。
第 2 步 — 设置 Webpack
Webpack 是最流行的 Web 开发打包工具之一。 它在处理您的应用程序时在内部构建 依赖关系图 。 该图映射了您的项目需要的每个模块并生成一个或多个捆绑包。 从 4.0.0 版本开始,webpack 不需要配置文件来打包你的项目; 然而,它是可配置的,以更好地满足您的需求。
让我们通过运行来安装它:
yarn add webpack --dev
我们还需要安装 webpack CLI:
yarn add webpack-cli --dev
安装这两个包后,您会注意到我们的项目中新增了一个,即我们的 package.json 文件中的 node_modules 和 devDependencies 部分。
接下来要做的是将刚刚安装的 webpack 添加到 package.json 文件中。
"scripts": {
"build": "webpack --mode production"
}
此时您不需要配置文件即可开始使用。
第 3 步 - 设置 Babel
现代 JavaScript 是用 ES6 或 ES7 编写的,但并不是每个浏览器都能理解这一点。 这里需要 babel 为我们做重光照。 Babel 是一个工具链,主要用于将 ECMAScript 2015+ 代码转换为当前和旧版浏览器或环境中向后兼容的 JavaScript 版本。 查看 Babel 文档 了解更多关于他们可以为你做什么的信息。
React 组件大多是用 ES6 编写的,带有导入、类和其他 ES6+ 特性的概念,这些都是旧版浏览器无法理解的。 Webpack 本身不知道如何将 ES6 代码转换或转译为 ES5 代码。 但它确实有 loader 的概念:webpack loader 接受类似于输入的东西并产生其他东西作为输出。
对于我们的设置,我们将使用 babel-loader,它是一个 webpack 加载器,它将为我们转译我们的 ES6 代码。 在我们开始使用 babel-loader 之前,我们需要安装一些包并设置 babel 预设 env,它将针对我们想要转译的特定 JavaScript 版本。
让我们安装所有依赖项:
yarn add @babel/core @babel/preset-env @babel/preset-react babel-loader --dev
我们还需要设置我们的 Babel 配置文件,在根目录中创建一个名为 .babelrc 的新文件,并将以下配置写入其中:
{
"presets": ["@babel/env", "@babel/react"]
}
这种配置将确保 Babel 将我们的 React 代码,即 JSX 和我们必须的任何其他 ES6+ 代码转换为 ES5 代码。
在根目录下创建一个webpack.config.js文件,并为其编写如下配置:
module.exports = {
module: {
rules: [
{
test: /.(js|jsx)$/,
exclude: /node_modules/,
use: {
loader: "babel-loader"
}
}
]
}
}
对于每个扩展名为 .js 或 .jsx 的文件,不包括 node_modules 文件夹及其内容,Webpack 使用 babel-loader 将 ES6 代码转译为 ES5。
完成后,让我们开始编写我们的 React 组件。
第 4 步 — 设置 React
我们将创建一个渲染文本和按钮的 React 组件,但是为了使用 React,我们需要安装一些依赖项: react 和 react-dom 。
yarn add react react-dom
安装后,在根目录中创建一个新文件夹。 我们称它为 src,并在其中创建一个 index.js 文件。
在index.js文件中,编写如下代码:
import React from "react";
import ReactDOM from "react-dom";
const Index = () => {
return (
<div className="full-screen">
<div>
<h1>
React Page {" "}
</h1>
<br />
<a
className="button-line"
href="https://github.com/deityhub"
target="_blank"
>
Know more
</a>
</div>
</div>
);
};
export default Index;
是时候测试一下了。 再次打开终端并运行:
yarn run build
你会看到一个由 Webpack 为我们创建的 dist 文件夹,里面有一个 index.js 文件,我们在其中有一个 ES5 代码的缩小版本。 在 package.json 中的构建脚本中,我们在 webpack 命令之后指定了 --mode production 标志; 这使得 Webpack 生成我们的 ES5 代码的缩小版本。 要查看转译代码的可读格式,您可以将 --mode production 与 --mode development 交换。
输出显示我们的代码有效,但我们希望我们的转译代码在浏览器中可见。 为此,让我们设置 HTML 和 CSS (SCSS) 以使用 Webpack。
第 5 步 — 将 React 组件连接到 DOM
我们需要设置一个 HTML 文件,以便我们的 React 组件可以在 DOM 上呈现。 为此,我们需要安装包 html-webpack-plugin:
yarn add html-webpack-plugin --dev
将 webpack.config.js 文件调整为如下所示:
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
module.exports = {
entry: path.join(__dirname, "src", "index.js"),
output: {
path: path.join(__dirname, "build"),
filename: "bundle.js"
},
module: {
rules: [
{
test: /.(js|jsx)$/,
exclude: /node_modules/,
use: {
loader: "babel-loader"
}
}
]
},
plugins: [
new HtmlWebpackPlugin({
filename: "index.html",
template: path.join(__dirname, "src", "index.html")
})
]
};
我们正在调整输入和输出,因此我们可以更好地控制文件的命名和目标。
接下来是在 src 文件夹中创建一个 HTML 文件; 我们称它为 index.html ,然后添加以下代码:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<title>React, Webpack, Babel Starter Pack</title>
<meta name="viewport" content="width=device-width, initial-scale=1" />
</head>
<body>
<noscript> You need to enable JavaScript to run this app. </noscript>
<!-- your react app will render here -->
<div id="app"></div>
</body>
</html>
由于我们在 src 目录中,让我们对我们的 React 组件进行一些调整。 首先,新建一个文件夹components,然后在这个文件夹中添加两个文件app.js和app.scss。 对我们的代码进行以下调整。
在 ./src/index.js 中:
import React from "react";
import ReactDOM from "react-dom";
import App from "./components/app";
ReactDOM.render(<App />, document.getElementById("app"));
在 ./src/components/app.js
import React from "react";
import "./app.scss";
const App = () => {
return (
<div className="full-screen">
<div>
<h1>
React Page {" "}
</h1>
<br />
<a
className="button-line"
href="https://github.com/deityhub"
target="_blank"
>
Know more now
</a>
</div>
</div>
);
};
export default App;
在 ./src/components/app.scss 中:
body {
background: linear-gradient(253deg, #0cc898, #1797d2, #864fe1);
background-size: 300% 300%;
-webkit-animation: Background 25s ease infinite;
-moz-animation: Background 25s ease infinite;
animation: Background 25s ease infinite;
}
.full-screen {
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
//you need to setup file-loader in webpack before you can use images
background: url("../../assests/image/background.png");
background-size: cover;
background-position: center;
width: 100%;
height: 100%;
display: -webkit-flex;
display: flex;
-webkit-flex-direction: column;
//_ works with row or column_
flex-direction: column;
-webkit-align-items: center;
align-items: center;
-webkit-justify-content: center;
justify-content: center;
text-align: center;
}
h1 {
color: #fff;
font-family: "Open Sans", sans-serif;
font-weight: 800;
font-size: 4em;
letter-spacing: -2px;
text-align: center;
text-shadow: 1px 2px 1px rgba(0, 0, 0, 0.6);
&:after {
display: block;
color: #fff;
letter-spacing: 1px;
font-family: "Poiret One", sans-serif;
content: "React project powered by webpack and babel with support for sass";
font-size: 0.4em;
text-align: center;
}
}
.button-line {
font-family: "Open Sans", sans-serif;
text-transform: uppercase;
letter-spacing: 2px;
background: transparent;
border: 1px solid #fff;
color: #fff;
text-align: center;
font-size: 1.4em;
opacity: 0.8;
padding: 20px 40px;
text-decoration: none;
transition: all 0.5s ease;
margin: 0 auto;
display: block;
&:hover {
opacity: 1;
background-color: #fff;
color: grey;
}
}
@-webkit-keyframes Background {
0% {
background-position: 0% 50%;
}
50% {
background-position: 100% 50%;
}
100% {
background-position: 0% 50%;
}
}
@-moz-keyframes Background {
0% {
background-position: 0% 50%;
}
50% {
background-position: 100% 50%;
}
100% {
background-position: 0% 50%;
}
}
@keyframes Background {
0% {
background-position: 0% 50%;
}
50% {
background-position: 100% 50%;
}
100% {
background-position: 0% 50%;
}
}
除了将在 DOM 中呈现的 HTML 和 React 组件之外,我们还将添加一些样式。 在我们运行我们的代码来测试它之前,我们需要配置我们的 Webpack,以便它知道如何处理通过它传递的任何 .css 或 .scss 文件。
yarn add css-loader sass-loader mini-css-extract-plugin node-sass --dev
Webpack 使用此处安装的 sass-loader 将我们的 .scss 转换为浏览器可以理解的 .css 文件,并在后台使用 node-sass为达到这个。 然后 mini-css-extract-plugin 将我们所有的 CSS 文件抽象成一个 CSS 文件,而不是 Webpack 提供的正常行为,即将你的 CSS 文件与最终的 .js 输出文件捆绑在一起,然后注入运行代码时将 CSS 放入呈现的 HTML 输出中。
打开你的 Webpack 配置文件并调整你的代码看起来像这样:
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = {
entry: path.join(__dirname, "src", "index.js"),
output: {
path: path.join(__dirname, "build"),
filename: "bundle.js"
},
module: {
rules: [
{
test: /.(js|jsx)$/,
exclude: /node_modules/,
use: {
loader: "babel-loader"
}
},
{
test: /.(css|scss)$/,
use: [MiniCssExtractPlugin.loader, "css-loader", "sass-loader"]
}
]
},
plugins: [
new HtmlWebpackPlugin({
filename: "index.html",
template: path.join(__dirname, "src", "index.html")
}),
new MiniCssExtractPlugin({
filename: "[name].css",
chunkFilename: "[id].css"
})
]
};
注意: 加载器在 Webpack 配置文件中的顺序很重要,因为 Webpack 从右到左处理加载器。 例如,对 CSS 文件使用测试将首先运行 sass-loader,然后是 css-loader,最后是 MiniCssExtractPlugin。
现在让我们安装 webpack 开发服务器。 这将为我们创建一个开发服务器,并监视我们的文件在开发过程中是否有任何更改。
yarn add webpack-dev-server --dev
然后打开您的 package.json 文件并在您的脚本标签中进行以下调整:
"scripts": {
"start": "webpack --mode development",
"dev": "webpack-dev-server --mode development --open",
"build": "webpack --mode production"
}
让我们通过运行 yarn run dev 来测试我们的代码。
您将在浏览器中看到类似这样的内容:
第 6 步 — 扩展功能
现在,让我们向这个项目添加另外两个特性,以演示在处理比这更高级的 React 项目时,您可以扩展或添加更多特性。
打开您的终端并安装这些软件包:
yarn add file-loader @babel/plugin-proposal-class-properties --dev
file-loader 将处理我们想要导入图像或 SVG 的所有场景,而 @babel/plugin-proposal-class-properties 将处理 React 类组件和静态类属性。
在 webpack.config.js 中将其调整为如下所示:
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = {
entry: path.join(__dirname, "src", "index.js"),
output: {
path: path.join(__dirname, "build"),
filename: "bundle.js"
},
module: {
rules: [
{
test: /.(js|jsx)$/,
exclude: /node_modules/,
use: {
loader: "babel-loader"
}
},
{
test: /.(css|scss)$/,
use: [MiniCssExtractPlugin.loader, "css-loader", "sass-loader"]
},
{
test: /.(jpg|jpeg|png|gif|mp3|svg)$/,
use: [
{
loader: "file-loader",
options: {
name: "[path][name]-[hash:8].[ext]"
}
}
]
}
]
},
plugins: [
new HtmlWebpackPlugin({
filename: "index.html",
template: path.join(__dirname, "src", "index.html")
}),
new MiniCssExtractPlugin({
filename: "[name].css",
chunkFilename: "[id].css"
})
]
};
在 .babelrc 文件中,也将其调整为如下所示:
{
"presets": ["@babel/env", "@babel/react"],
"plugins": ["@babel/plugin-proposal-class-properties"]
}
最后,运行 yarn run dev 以确保一切正常。
结论
以此作为 React 应用程序的基础,您可以扩展配置并从中构建一些东西。 如果遇到困难,请查看 GitHub 链接 以获取完整代码。