如何将 ReactJS 与 Webpack 4、Babel 7 和 Material Design 结合使用
过去一年多来,我一直在Creative Tim团队使用 React 开发。我使用create-react-app开发了一些不错的产品。很多客户问我,如何将我们的产品模板迁移到 Webpack 上。
因此,在收到大量请求后,我们创建了这个关于如何开始使用React和Webpack 4以及Babel 7 的小教程。在教程的最后,我将向大家展示如何在新创建的应用程序上添加Material Dashboard React 。
在开始之前,请确保您的计算机上全局安装了最新版本的npm和Nodejs。撰写本文时,我的计算机上 npm 的最新版本是 6.4.1,Nodejs 的最新版本是 8.12.0 (lts)。
使用 package.json 创建新的项目文件夹
首先,让我们为我们的新应用程序创建一个新文件夹并输入它:
mkdir react-webpack-babel-tutorialcd react-webpack-babel-tutorial
现在我们已经创建了用于开发应用程序的文件夹,我们需要向其中添加一个package.json文件。我们可以通过两种方式来实现,您可以选择其中一种:
1-只需创建package.json文件,无需任何其他配置:
npm init -y
如您所见,package.json文件已经创建,其中包含一些非常基本的信息。 |npm init -y output|
2-创建带有一些额外配置设置的package.json文件
npm init
我已经在我们新创建的package.json文件中添加了一些内容,例如一些不错的关键字、一个 repo等等……
之后,让我们将index.html和index.js文件添加到新项目文件夹的src文件夹内。
- Linux/MacOS 命令
mkdir srctouch src/index.htmltouch src/index.js
- Windows 命令
mkdir srcecho "" > src\index.htmlecho "" > src\index.js
之后,让我们在index.html中添加以下模板。
<!DOCTYPE html><html lang="en"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> <meta name="theme-color" content="#000000"> <title>React Tutorial</title> </head> <body> <noscript> You need to enable JavaScript to run this app. </noscript> <div id="root"></div> <!-- This HTML file is a template. If you open it directly in the browser, you will see an empty page. You can add webfonts, meta tags, or analytics to this file. The build step will place the bundled scripts into the <body> tag. --> </body></html>
为了展示我们稍后将要看到的,我们在index.js中添加一些内容。
(function () { console.log("hey mister");}());
这是我们目前得到的结果:
将 Webpack 添加到项目
让我们开始添加所有需要的Webpack包。我们将把它们安装为devDependencies,因为它们只在开发模式下使用。
npm install --save-dev webpack webpack-cli webpack-dev-server
- webpack
- 用于配置我们的新应用程序
- 截至本文发布时,版本为4.19.0
- webpack-cli
- 这样我们就可以在命令行中使用 Webpack
- 截至本文发布时,版本为3.1.0
- webpack-dev-server
- 这样,当我们在新应用中更改文件时,就无需刷新页面。每次我们在应用中更改文件时,它都会自动刷新浏览器页面
- 正如其名称所示,这是一个不间断工作的服务器
- 截至本文发布时,版本为3.1.8
|npm install — save-dev webpack webpack-cli webpack-dev-server 输出|
如果我们查看package.json文件,我们会看到这三个包被添加到这个文件中,如下所示:"devDependencies": { "webpack": "^4.19.0", "webpack-cli": "^3.1.0", "webpack-dev-server": "^3.1.8"}
我打算把每个版本中的^(插入符号)都删掉。这是因为我不确定这些插件的下一个版本是否还能兼容我正在构建的应用。我认为这应该是一个常识。创建新应用时,请使用现有版本,然后再更新到新版本。你可能不知道新版本会给你的应用带来哪些问题。
正如你所见,这些插件的安装对我们的项目文件夹进行了一些更改。它添加了node_modules文件夹和package-lock.json。
现在,我们需要向我们的项目添加一个新文件,即Webpack的配置文件,名为webpack.config.js:
- Linux/MacOS 命令
touch webpack.config.js
- Windows 命令
echo "" > webpack.config.js
或者,如果您不想使用命令行,您可以简单地手动创建新文件。
在我们继续处理Webpack 配置文件之前,让我们先安装一些我们应用程序中需要的东西。
首先,我们将处理 Webpack 配置文件中的一些路径。让我们将路径作为devDependency安装到项目中。
npm install --save-dev path
另外,由于我们不想手动将index.js文件注入到 HTML 文件中,我们需要一个名为html-webpack-plugin 的插件。这个插件会将index.js注入到 HTML 文件中,无需任何手动操作。
npm install --save-dev html-webpack-plugin
再次,我将编辑我的package.json文件并从中删除所有 ^(插入符号)。
我们要对package.json进行的另一项编辑是在测试脚本之后在脚本对象内添加一些新脚本(参见下面的第二个示例)。
"webpack": "webpack","start": "webpack-dev-server --open"
此时你的package.json应该是这样的:
{ "name": "react-webpack-babel-tutorial", "version": "1.0.0", "description": "This is a Tutorial to showcase the usage of React with Webpack and Babel", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1", "webpack": "webpack", "start": "webpack-dev-server --open" }, "repository": { "type": "git", "url": "git+https://github.com/creativetimofficial/react-webpack-babel-tutorial.git" }, "keywords": [ "react", "webpack", "babel", "creative-tim", "material-design" ], "author": "Creative Tim <hello@creative-tim.com> (https://www.creative-tim.com/)", "license": "MIT", "bugs": { "url": "https://github.com/creativetimofficial/react-webpack-babel-tutorial/issues" }, "homepage": "https://github.com/creativetimofficial/react-webpack-babel-tutorial#readme", "devDependencies": { "html-webpack-plugin": "3.2.0", "path": "0.12.7", "webpack": "4.19.0", "webpack-cli": "3.1.0", "webpack-dev-server": "3.1.8" }}
让我们继续逐个运行这些命令,看看会发生什么。
npm run webpack
Webpack会自动获取src/index.js文件,进行编译,并将其输出到dist/main.js中,并压缩该代码。这是因为我们尚未配置Webpack 配置文件。此外,由于我们尚未配置该文件,控制台中将会显示一些警告。
如果我们运行另一个命令:
npm start
webpack-dev-server会自动启动一个服务器,并使用该服务器打开默认浏览器。但是,由于我们没有配置webpack.config.js文件,因此输出结果可能与预期不同。
如果您想停止服务器,只需在命令行中同时按下CTRL + C键。
让我们在Webpack 配置文件中添加以下模板:
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: 'index.bundle.js' }, mode: process.env.NODE_ENV || 'development', resolve: { modules: [path.resolve(__dirname, 'src'), 'node_modules'] }, devServer: { contentBase: path.join(__dirname,'src') }, plugins: [ new HtmlWebpackPlugin({ template: path.join(__dirname,'src','index.html') }) ]};
- 入口和输出
- 这些用于告诉我们的服务器需要编译什么以及从哪里编译(entry: path.join(__dirname,'src','index.js'),)。它还告诉将输出的编译版本放在哪里(输出- 文件夹和文件名)
- 模式
- 这是我们输出的模式。我们将其设置为“development”。如果我们在脚本中指定了NODE_ENV 变量,它将改为使用这个变量。请参阅以下示例了解如何使用NODE_ENV (请注意,本教程中不会在 package.json 文件中进行以下更改,这只是一个示例,供您了解其工作原理)。
"webpack": "NODE_ENV=production webpack",
- 解决
- 这样做是为了让我们可以从src文件夹导入任何内容,而不是使用绝对路径。node_modules 也一样。我们可以直接从 node_modules 导入任何内容,而无需使用绝对路径。
- 开发服务器
- 这会告诉webpack-dev-server需要提供哪些文件。src 文件夹中的所有内容都需要在浏览器中提供(输出)。
- 插件
- 这里我们设置了应用中需要的插件。目前我们只需要html-webpack-plugin 插件,它会告诉服务器应该将index.bundle.js注入(或者,如果你愿意,也可以直接添加到)到我们的index.html文件中。
如果我们现在运行之前的命令,我们会看到一些差异。
npm run webpack
|npm 使用 webpack.config.js 运行 webpack 输出|
我们更改了输出的位置(从dist文件夹移到了build文件夹)。通过更改Webpack的模式,现在代码看起来有所不同。它不像上次没有config时那样被压缩了。
npm start
webpack -dev-server从src文件夹中获取所有内容并将其输出到我们的浏览器。
我们已经走在正确的道路上,但我们只在项目中添加了 Webpack。React 和 Babel 在哪里?好吧,这就是我们接下来要做的。
React、Babel 和一些不错的样式加载器
将React和ReactDOM作为常规依赖项添加到我们的项目中。
npm install --save react react-dom
在开发过程中,如果我们在 JS 文件中添加React代码, Webpack会报错。它不知道如何在bundle.js文件中编译React。
我们来修改一下index.js文件,如下所示:
import React from "react";import ReactDOM from "react-dom";let HelloWorld = () => { return <h1>Hello there World!</h1>}ReactDOM.render( <HelloWorld/>, document.getElementById("root"));
之后让我们重新启动服务器。
npm start
这是错误: |由于没有适合react的加载器而导致的 webpack错误|
这时Babel就派上用场了。Babel会告诉Webpack如何编译我们的React代码。
让我们继续将一堆 Babel 包作为devDependencies添加到我们的应用程序中。
npm install --save-dev @babel/core @babel/node @babel/preset-env @babel/preset-react babel-loader
- @babel /核心
- 用于将ES6及以上版本编译为ES5
- @babel /节点
- 这样做是为了我们可以在webpack.config.js中导入我们的插件和包,而不是需要它们(这只是我喜欢的东西,也许你也会喜欢它)
- @babel /preset-env
- 这将根据您想要支持的浏览器矩阵来确定使用哪些转换或插件以及 polyfill(即,它在不支持它的旧版浏览器上提供现代功能)
- @babel /预设反应
- 这将把React代码编译成ES5代码
- babel-loader
- 这是一个Webpack助手,它使用Babel转换你的JavaScript依赖项(即将import语句转换为require语句)
由于您可能需要在项目中添加一些样式(我知道我需要它们),我们将添加一个加载器,以便我们导入和使用CSS 文件和SCSS文件。
npm install --save-dev style-loader css-loader sass-loader node-sass
- 样式加载器
- 这将向DOM添加样式(将注入一个HTML 文件内的标签)
- css加载器
- 将允许我们将CSS文件导入到我们的项目中
- sass-loader
- 将允许我们将SCSS文件导入到我们的项目中
- 节点-sass
- 将SCSS文件编译为普通CSS文件
我们将创建一个新的SCSS文件并将其添加到我们的文件夹中。
- Linux/MacOS 命令
touch src/index.scss
- Windows 命令
echo "" > src/index.scss
并且还添加一些漂亮的样式。
body { div#root{ background-color: #222; color: #8EE4AF; }}
并通过添加SCSS文件的导入来更改我们的index.js。
import React from "react";import ReactDOM from "react-dom";
// this line is new// we now have some nice styles on our react appimport "index.scss";
let HelloWorld = () => { return <h1>Hello there World!</h1>}
ReactDOM.render( <HelloWorld/>, document.getElementById("root"));
不要忘记从package.json中删除插入符号 (^) 。
你的package.json应该是这样的:
{ "name": "react-webpack-babel-tutorial", "version": "1.0.0", "description": "This is a Tutorial to showcase the usage of React with Webpack and Babel", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1", "webpack": "webpack", "start": "webpack-dev-server --open" }, "repository": { "type": "git", "url": "git+https://github.com/creativetimofficial/react-webpack-babel-tutorial.git" }, "keywords": [ "react", "webpack", "babel", "creative-tim", "material-design" ], "author": "Creative Tim <hello@creative-tim.com> (https://www.creative-tim.com/)", "license": "MIT", "bugs": { "url": "https://github.com/creativetimofficial/react-webpack-babel-tutorial/issues" }, "homepage": "https://github.com/creativetimofficial/react-webpack-babel-tutorial#readme", "devDependencies": { "@babel/core": "7.0.1", "@babel/node": "7.0.0", "@babel/preset-env": "7.0.0", "@babel/preset-react": "7.0.0", "babel-loader": "8.0.2", "css-loader": "1.0.0", "html-webpack-plugin": "3.2.0", "node-sass": "4.9.3", "path": "0.12.7", "sass-loader": "7.1.0", "style-loader": "0.23.0", "webpack": "4.19.0", "webpack-cli": "3.1.0", "webpack-dev-server": "3.1.8" }, "dependencies": { "react": "16.5.1", "react-dom": "16.5.1" }}
如果我们再次运行上述任何命令,错误仍然会存在。我们还没有告诉Webpack它应该使用Babel和样式加载器来编译我们的React和SCSS代码。
接下来要做的是为Babel添加一个配置文件。为此,我们需要创建一个名为.babelrc的文件,我们将在其中配置Babel。
我听说你可以直接在webpack.config.js文件中添加Babel的配置。关于这一点,你可以查看官方的 babel-loader 文档。就我而言,我认为最好将Babel的配置放在一个单独的文件中。这样你的Webpack 配置就不会过于拥挤。
因此,让我们在命令行中运行以下命令:
- Linux/MacOS 命令
touch .babelrc
- Windows 命令
echo "" > .babelrc
并在.babelrc中添加以下代码,以便babel-loader知道使用什么来编译代码:
{ "presets": [ "@babel/env", "@babel/react" ]}
完成这些步骤后,我们需要在项目中添加一些内容,以便导入各种文件,例如图片。我们还需要添加一个插件,以便处理类等等。让我们在类中添加类属性。基本上,它能让我们进行面向对象编程——太棒了。
npm install --save-dev file-loader @babel/plugin-proposal-class-properties
现在我们已经完成了这些,我们需要在webpack.config.js中做一些修改,以便Webpack现在可以使用Babel。我们还将配置Webpack来监听样式文件,并将 require 语句更改为 import 样式文件。
因此,让我们将webpack.config.js更改为以下内容(我还添加了一些注释,也许它们会对您有所帮助):
// old// const path = require('path');// const HtmlWebpackPlugin = require('html-webpack-plugin');// newimport path from 'path';import HtmlWebpackPlugin from 'html-webpack-plugin';module.exports = { entry: path.join(__dirname,'src','index.js'), output: { path: path.join(__dirname,'build'), filename: 'index.bundle.js' }, mode: process.env.NODE_ENV || 'development', resolve: { modules: [path.resolve(__dirname, 'src'), 'node_modules'] }, devServer: { contentBase: path.join(__dirname,'src') }, module: { rules: [ { // this is so that we can compile any React, // ES6 and above into normal ES5 syntax test: /\.(js|jsx)$/, // we do not want anything from node_modules to be compiled exclude: /node_modules/, use: ['babel-loader'] }, { test: /\.(css|scss)$/, use: [ "style-loader", // creates style nodes from JS strings "css-loader", // translates CSS into CommonJS "sass-loader" // compiles Sass to CSS, using Node Sass by default ] }, { test: /\.(jpg|jpeg|png|gif|mp3|svg)$/, loaders: ['file-loader'] } ] }, plugins: [ new HtmlWebpackPlugin({ template: path.join(__dirname,'src','index.html') }) ]};
我们还需要在package.json文件上做一点修改。我们需要告诉脚本,在Webpack的配置文件中使用import 语句,而不是require语句。否则,它会报错,说它不知道import代表什么。
{ "name": "react-webpack-babel-tutorial", "version": "1.0.0", "description": "This is a Tutorial to showcase the usage of React with Webpack and Babel", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1", "webpack": "babel-node ./node_modules/webpack/bin/webpack", "start": "babel-node ./node_modules/webpack-dev-server/bin/webpack-dev-server --open" }, "repository": { "type": "git", "url": "git+https://github.com/creativetimofficial/react-webpack-babel-tutorial.git" }, "keywords": [ "react", "webpack", "babel", "creative-tim", "material-design" ], "author": "Creative Tim <hello@creative-tim.com> (https://www.creative-tim.com/)", "license": "MIT", "bugs": { "url": "https://github.com/creativetimofficial/react-webpack-babel-tutorial/issues" }, "homepage": "https://github.com/creativetimofficial/react-webpack-babel-tutorial#readme", "devDependencies": { "@babel/core": "7.0.1", "@babel/node": "7.0.0", "@babel/plugin-proposal-class-properties": "7.0.0", "@babel/preset-env": "7.0.0", "@babel/preset-react": "7.0.0", "babel-loader": "8.0.2", "css-loader": "1.0.0", "file-loader": "2.0.0", "html-webpack-plugin": "3.2.0", "node-sass": "4.9.3", "path": "0.12.7", "sass-loader": "7.1.0", "style-loader": "0.23.0", "webpack": "4.19.0", "webpack-cli": "3.1.0", "webpack-dev-server": "3.1.8" }, "dependencies": { "react": "16.5.1", "react-dom": "16.5.1" }}
我们还需要将@babel /plugin-proposal-class-properties添加到.babelrc文件。Babel 知道如何处理类属性。
{ "presets": [ "@babel/env", "@babel/react" ], "plugins": [ "@babel/plugin-proposal-class-properties" ]}
现在我们完成了。我们可以运行上述任意一个命令,并且不会出现任何错误。让我们看看它们的实际效果。
npm run webpack
现在让我们看看我们的应用程序的主要脚本。
npm start
`
将 Material Design 添加到我们新的 React with Webpack 和 Babel 项目中
正如我在文章开头所说,我们不会从头开始创建 Material Design 的样式。那样会很费劲,我们没时间。
相反,我们将添加一个优秀的产品,它实现了Google 的 Material Design,并由Creative Tim 的员工进行了一些小改动。我们将向其中添加Material Dashboard React 。
首先,你需要获得产品。以下是获取产品的几种方式:
- 将 repo 克隆到另一个文件夹中:
git clone https://github.com/creativetimofficial/material-dashboard-react.git
好的,现在我们有两个项目 - Material Dashboard React 和我们用Webpack和Babel新创建的项目- 使用React。
|material-dashboard-react 和 react-webpack-babel-tutorial|
现在,我们不能简单地将Material Dashboard React中的 src 文件夹复制到新项目中。那样会报很多错误,比如缺少依赖项、找不到模块等等。
因此,我建议我们先将Material Dashboard React 的 package.json中的依赖项添加到我们的package.json中。由于我们已经使用 Webpack 构建了自己的服务器,因此不需要Material Dashboard React packages中的所有依赖项。除了产品本身的功能外,我们还添加了其他样式加载器。
因此,我们需要以下内容:
npm install --save @material-ui/core@3.1.0 @material-ui/icons@3.0.1 @types/googlemaps@3.30.11 @types/markerclustererplus@2.1.33 chartist@0.10.1 classnames@2.2.6 perfect-scrollbar@1.4.0 react-chartist@0.13.1 react-google-maps@9.4.5 react-router-dom@4.3.1 react-swipeable-views@0.12.15
我们不会一一介绍它们。你可以在npmjs.com上找到它们的详细信息以及各自的文档。
再次,我们进入package.json文件并从刚刚安装的包中删除插入符号 (^)。
好的,我们快完成了。我们将把Material Dashboard React中src文件夹的所有内容复制到我们项目的src文件夹中,并覆盖index.js文件。但请保留index.html文件中的内容。
|添加 Material Dashboard React src 文件夹前后的文件夹结构|
现在我们需要在index.html中添加一些样式和字体 cdn 。
<!DOCTYPE html><html lang="en"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> <meta name="theme-color" content="#000000"> <link rel="stylesheet" href="//cdn.jsdelivr.net/chartist.js/latest/chartist.min.css"> <script src="//cdn.jsdelivr.net/chartist.js/latest/chartist.min.js"></script> <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700|Material+Icons"> <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet"> <title>React Tutorial</title> </head> <body> <noscript> You need to enable JavaScript to run this app. </noscript> <div id="root"></div> <!-- This HTML file is a template. If you open it directly in the browser, you will see an empty page. You can add webfonts, meta tags, or analytics to this file. The build step will place the bundled scripts into the <body> tag. --> </body></html>
差不多就完成了。不过还有一个小问题。刷新页面时,会报错“无法获取 /dashboard”。如果导航到其他页面,则会报错,例如“无法获取 /user”等等。所以,我们的路由根本就不起作用。我们需要在src/index.js或webpack.config.js中修改一下。
我会选择第一个选项,因为它非常简单且易于理解。
我们在新的 index.js 中导航,并更改了历史记录类型。我们将createBrowserHistory()替换为createHashHistory()。
这样我们就可以刷新页面而不会出现任何其他错误。现在我们完成了。
import React from "react";import ReactDOM from "react-dom";import { createHashHistory } from "history";import { Router, Route, Switch } from "react-router-dom";import "assets/css/material-dashboard-react.css?v=1.5.0";import indexRoutes from "routes/index.jsx";const hist = createHashHistory();ReactDOM.render( <Router history={hist}> <Switch> {indexRoutes.map((prop, key) => { return <Route path={prop.path} component={prop.component} key={key} />; })} </Switch> </Router>, document.getElementById("root"));
我真心希望你喜欢这篇教程,也非常期待听到你的想法。欢迎在这条帖子里留言,我很乐意回复。
还要特别感谢Linh Nguyen My 的教程,它让我对Webpack有了更多的了解。
有用的链接:
- 从Github获取本教程的代码
- 在其官方网站上了解有关ReactJS 的更多信息
- 点击此处了解有关Webpack的更多信息
- 点击此链接了解有关 Babel 的更多信息
- 阅读有关材料设计的更多信息
- 查看我们的平台,了解我们在做什么以及我们是谁
- 从www.creative-tim.com或Github获取 Material Dashboard React
- 阅读有关Material-UI 的更多信息,它是 Material Dashboard React 的核心
找到我:
- 电子邮件: manu@creative-tim.com
- 脸书:https://www.facebook.com/NazareEmanuel
- Instagram:https://www.instagram.com/manu.nazare/