想阅读更多优质文章请猛戳GitHub博客,一年百来篇优质文章等着你!
在过去的一年和一些人中,我一直在与 Creative Tim 合作。 我一直在使用 create-react-app 来开发一些不错的产品。 有很多客户询问如何在 Webpack 上迁移我们的产品模板。
在多次要求求之后,我们写了这个关于如何开始使用 React with Webpack 4和 Babel 7 的小教程。在本教程的最后,将向大家展示如何在新创建的应用程序上添加 Material Dashboard React。
在我们开始之前,请确保你的电脑上安装了 npm 和 Nodejs 的最新版本。在撰写本文时,我的电脑上的最新版本是 npm 的 6.4.1
和 Nodejs 的 8.12.0
(lts)。
建立项目
首先,创建工程目录:
mkdir react-webpack-babel-tutorial
cd react-webpack-babel-tutorial
现在我们已经创建了我们要开发应用程序的文件夹,接着需要添加一个 package.json
文件。 有两种创建方式,你可以选择其中的一种:
1.只需创建 package.json 文件,无需任何其他配置:
npm init -y
如下所示,package.json 文件已创建,其中包含一些非常基本的信息。
2.使用一些额外的配置设置创建 package.json 文件
npm init
我在我们新创建的 package.json 文件中添加了一些东西,比如一些很好的 keywords,一个repo等等...
之后,在根目录下创建 src 文件夹,然后在 src 下分别创建 index.html
和 index.js
.
1.Linux / MacOS 命令
mkdir src
touch src/index.html
touch src/index.js
2.Windows 命令
mkdir src
echo "" > src\index.html
echo "" > 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 添加到项目中
安装 Webapck 及所需的开发环境依赖模块。
npm install --save-dev webpack webpack-cli webpack-dev-server
-
- 用来配置我们的新应用
- 本文所用的版本是 4.19.0
-
- 可以在命令行中使用 Webpack 了
- 本文所用的版本是 3.1.0
-
- 这样,当我们对新应用程序中的文件进行更改时,就不需要刷新页面了。每当我们在应用程序中更改文件时,它会自动刷新浏览器页面
- 本文所用的版本是 3.1.8
看一下package.json文件,将看到这三个包被添加到这个文件中,如下所示:
"devDependencies": {
"webpack": "^4.19.0",
"webpack-cli": "^3.1.0",
"webpack-dev-server": "^3.1.8"
}
补充说明一下版本号前的 ^,~ 的区别
- 指定版本:比如"webpack": "4.19.0",表示安装 4.19.0 的版本
- 波浪号
~
指定版本:比如 "webpack-cl": "~3.1.0",表示安装3.1.0
的最新版本(不低于1.1.0),但是不安装1.2.x
,也就是说安装时不改变大版本号和次要版本号 -
^
指定版本:比如 "webpack-dev-server": "^3.1.8",,表示安装请输入代码
3.1.4 及以上的版本,但是不安装4.0.0,也就是说安装时不改变大版本号。
package.json
文件只能锁定大版本,也就是版本号的第一位,并不能锁定后面的小版本,你每次 npm install
都是拉取的该大版本下的最新的版本,为了稳定性考虑我们几乎是不敢随意升级依赖包的,这将导致多出来很多工作量,测试/适配等,所以 package-lock.json
文件出来了,当你每次安装一个依赖的时候就锁定在你安装的这个版本。
所以当我们 npm install
安装完插件后,都会生成两个文件一个是 node_modules 和 package-lock.json 。
这里为了版本的一致性,我把 package.json 里的 版本号前面 ^
删除了。
接着新建 Webpack 配置文件 webpack.config.js:
1.Linux/MacOS 命令
touch webpack.config.js
2.Windows 命令
echo "" > webpack.config.js
如果你不想使用命令行,也可以简单地手动创建文件。
在开始处理 Webpack 配置文件之前,先在应用程序中安装一些我们需要的东西。
首先安装 path 作为开发环境的路径依赖。
npm install --save-dev path
此外,由于不想在 HTML 中手动注入 index.js 文件,因此需要安装 html-webpack-plugin 的插件。 此插件通过配置在 HTML 文件中注入 index.js,无需手动操作。
npm install --save-dev html-webpack-plugin
再次,我将 package.json 文件删除所有 ^
。
安装完后在 package.json 文件中的 scripts 属性里添加以为内容:
"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.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: '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')
})
]
};
1.entry
entry 可以是个字符串或数组或者是对象。 当 entry 是个字符串的时候,用来定义入口文件:
entry: './js/main.js'
当 entry 是个数组的时候,里面同样包含入口js文件,另外一个参数可以是用来配置webpack提供的一个静态资源服务器,webpack-dev-server。webpack-dev-server 会监控项目中每一个文件的变化,实时的进行构建,并且自动刷新页面:
entry: [
'webpack/hot/only-dev-server',
'./js/app.js'
]
当 entry 是个对象的时候,我们可以将不同的文件构建成不同的文件,按需使用,比如在我的 hello 页面中只要\
引入 hello.js 即可:
entry: {
hello: './js/hello.js',
form: './js/form.js'
}
2.output
output 参数是个对象,用于定义构建后的文件的输出。其中包含 path 和 filename:
output: {
path: './build',
filename: 'bundle.js'
}
3.mode
这是输出的模式,这里将其 mode 设置为 “development”。如果在脚本中指定 NODE_ENV 变量,那么它将使用这个变量。请参阅下面关于如何使用 NODE_ENV 的示例(请注意,本教程中的 package.json 文件中不会进行以下更改,这只是一个示例,可以看到它是如何工作的)
"webpack": "NODE_ENV=production webpack",
4.resolve
webpack 在构建包的时候会按目录的进行文件的查找,resolve 属性中的 extensions
数组中用于配置程序可以自行补全哪些文件后缀:
resolve:{
extensions:['','.js','.json']
}
5.devServer
这告诉 webpack-dev-server 需要提供哪些文件。 这里是 src
文件夹中的所有内容都需要在浏览器中浏览。
6.plugins
在这里,我们设置了我们的应用程序中需要的插件。到目前为止,只需要 html-webpack-plugin,它告诉服务器 index.bundl.js 应该被注入到 index.html 文件中
再次运行以下命令,显示会跟上一次不同:
npm run webpack
webpack-dev-server 从 src 文件夹中读取所有内容并输出到我们的浏览器中。
配置 React,Babel 与 styles loaders
通过运行以下命令来引入 React :
npm i react react-dom --save-dev
在我们的开发过程中,如果我们在 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
错误如下:
所以这就是 Babel 出现的原因, Babel 将告诉 Webpack 如何编译 React 代码。
安装 Babel 相关依赖:
npm install --save-dev @babel/core @babel/node @babel/preset-env @babel/preset-react babel-loader
@babel/core
这是将ES6及以上版本编译成ES5
@babel/node
babel-node
是 babel-cli
的一部分,它不需要单独安装。
它的作用是在 node 环境中,直接运行 es2015 的代码,而不需要额外进行转码。例如我们有一个 js 文件以 es2015 的语法进行编写(如使用了箭头函数)。我们可以直接使用 babel-node es2015.js
进行执行,而不用再进行转码了。
可以说:babel-node = babel-polyfill + babel-register
@babel/preset-react
这个是把 React 代码编译成 ES5 代码。
babel-loader
和 babel-cli
一样,babel-loader 也会读取 .babelrc
或者 package.json
中的 babel
段作为自己的配置,之后的内核处理也是相同。唯一比 babel-cli
复杂的是,它需要和 webpack 交互,因此需要在 webpack 这边进行配置。比较常见的如下:
module: {
rules: [
{
test: /\.js$/,
exclude: /(node_modules|bower_components)/,
loader: 'babel-loader'
}
]
}
如果想在这里传入 babel
的配置项,也可以把改成:
// loader: 'babel-loader' 改成如下:
use: {
loader: 'babel-loader',
options: {
// 配置项在这里
}
}
我们需要为项目中添加一些样式,此时就需要使用样式相关的加载器,这边使用 scss
,安装命令如下:
npm install --save-dev style-loader css-loader sass-loader node-sass
style-loader
通过注入 <style>
标签将 CSS 添加到 DOM 中
css-loader
css-loader用于将 css 文件打包到js中, 常常配合 style-loader 一起使用,将 css 文件打包并插入到页面中
sass-loader
加载 SASS/SCSS 文件
node-sass
将 SCSS 文件编译为 CSS 文件
在 src 下创建 scss 文件:
1.Linux/MacOS 命令
touch src/index.scss
2.window 命令
echo "" > src/index.scss
并添加以下内容:
body {
div#root{
background-color: #222;
color: #8EE4AF;
}
}
接着导入 index.js 中
import React from "react";
import ReactDOM from "react-dom";
// this line is new
// we now have some nice styles on our react app
import "index.scss";
let HelloWorld = () => {
return <h1>Hello there World!</h1>
}
ReactDOM.render(
<HelloWorld/>,
document.getElementById("root")
);
记得删除 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-loa
der": "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 配置过于复杂难读。
在根目录下创建 .babelrc
1.Linux/MacOS 命令
touch .babelrc
2.Windows 命令
echo "" > .babelrc
并在 .babelrc 中添加以下代码,这样 babel-loader 就会知道用什么来编译代码:
{
"presets": [
"@babel/env",
"@babel/react"
]
}
完成这些步骤后,我们需要在项目中添加一些内容,以便我们可以导入各种文件,如图像。 还需要添加一个插件,让我们可以使用类等等。 让我们在类中添加类属性,基本上,它将让我们能够使用 面向对象编程 方式来编写代码。
因此,让我们将 webpack.config.js 更改为以下内容(我也添加了一些注释,可能会对你有所帮助):
// old
// const path = require('path');
// const HtmlWebpackPlugin = require('html-webpack-plugin');
// new
import 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: [
{
// 这样我们就可以将React、ES6及以上的任何内容编译成正常的ES5语法
test: /\.(js|jsx)$/,
// 不希望编译node_modules中的任何内容
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"
}
}
我们还需要在 .babelrc 文件中添加 @babel/plugin-proposal-class 属性,Babel将会知道如何处理类属性。
{
"presets": [
"@babel/env",
"@babel/react"
],
"plugins": [
"@babel/plugin-proposal-class-properties"
]
}
现在总算配置完成了。再次运行上述任何一个命令,就可以顺利跑起来啦。
npm run webpack
npm start
使用 Webpack 和 Babel 项目将 Material Design 加到我们的新 React 项目中
正如在这篇文章的开头讲的,我们不会讲 Material Design 样式如何写,这需要大量的工作。
相反,这里添加一个很好的产品来实现 Google 的 Material Design,其中包括Creative Tim 员工的一些小改动。 我们将向其添加 Material Dashboard React。
首先从 github 上把项目拷贝下来:
git clone https://github.com/creativetimofficial/material-dashboard-react.git
- Download from Github
好的,现在我们有两个项目 - Material Dashboard React 和 我们刚创建的项目。
现在,我们不能简单地将 src 文件夹从 Material Dashboard React 复制到我们的新项目中。 这会给我们带来很多错误, 如缺少依赖关系的错误,找不到模块等。
因此,我建议首先将 Material Dashboard React 的 package.json 中的依赖项添加到 package.json 中。 我们不需要 Material Dashboard React 包中的所有依赖项,因为我们使用 Webpack 构建了自己的服务器。 除了产品本身,我们还添加了其他样式加载器。
所以说,我们需要如下:
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 下
好了,差不多做完了,我们拷贝 Material Dashboard React 下的 src文件中所有内容到我们项目 src 下,并覆盖 index.js 文件。但是要保留 index.html 文件。
拷贝前
拷贝后
现在需要在 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">
<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>
还有一个小问题。 当我们刷新页面时,有一个错误 Cannot GET/dashboard
。 如果我们跳转到另一个页面,会得到如, Cannot GET /user
错误等 。 所以根本上,我们的路由不起作用,需要在 src/index.js
或 webpack.config.js 中进行一些更改。
这里选择使用第一个方案,因为它非常简单易懂。
我们在新导航方式在 index.js 更改 history,使用 createHashHistory() 替换 createBrowserHistory()。
这将允许我们刷新页面而不会出现任何其他错误,现在我们完成了。
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")
);
原文:
https://medium.freecodecamp.o...
你的点赞是我持续分享好东西的动力,欢迎点赞!
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。