如何使用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 链接 以获取完整代码。