@gyyin
2020-03-29T23:47:41.000000Z
字数 5719
阅读 278
慕课专栏
从这篇开始,将会带大家一起来学习 React 的相关知识。React 是当前最火的前端框架之一,但它本身的语法不可以直接在浏览器端运行,所以在正式开始学习 React 之前,我想带领大家先学习一下如何搭建 React 环境。
随着前端的迅速发展,ECMAScript 语法也变得越来越完善,NodeJS 诞生后各种自动化的工具像雨后春笋一样冒出来。
前端的需求也越来越多,比如我们要将 ES6、JSX 等语法转成浏览器可以识别的,于是 Babel 诞生了。我们需要对代码进行压缩、编译、单元测试等等,之前流行的是 Grunt,后来是 Gulp,现在则是 webpack,前端工具处于不断发展完善之中。
今天,我们将会用 webpack 和 Parcel 来搭建 React 环境。
本文不会对两者语法和用处进行详细地讲解,有需要的同学可以自行查阅资料。
webpack 是一个前端资源加载/打包工具。它将根据模块的依赖关系进行静态分析,然后将这些模块按照指定的规则生成对应的静态资源。
webpack 会分析项目结构,找到 JavaScript 模块以及一些不能直接运行的语言(Sass、TypeScript等),将其转换供浏览器使用。
在安装 webpack 之前,需要先安装 NodeJS 和 npm 环境,这里不作讲解,可以参考廖雪峰的这篇文章:安装Node.js和npm
首先,我们先创建一个项目,安装 webpack 依赖。
mkdir webpack-react
cd webpack-react
npm init // 初始化
npm i webpack webpack-cli -D // 安装相关包
npm i 就是 npm install,-D 就是 -dev.
我们先来写个简单的 hello, world
,在 package.json
的 scripts
里面配置一下。在 webpack4 里面,允许我们不写 webpack.config.js
。
// index.js
console.log("hello, world")
当然,只是简单地使用,这样就够了,更多情况下我们还是要手写配置文件。
在 webpack 中,有 loader 和 plugin 两个概念。
loader 是一个转换器,它描述了怎么处理模块,比如将 TypeScript 转换为 JavaScript,将内联的图像转换为 data url 等等。
而 plugin 则是解决一些 loader 无法实现的其他事,比如代码压缩、去除 console.log
等等,可以用来处理各种各样的任务。
我们来创建一个 webpack 配置文件,在根目录下新建一个 webpack.config.js
文件。
const path = require('path');
module.exports = {
mode: 'development', // 开发模式
entry: path.resolve(__dirname,'./src/index.js'), // 入口文件
output: {
filename: 'build.js', // 打包后的文件名称
path: path.resolve(__dirname,'./dist') // 打包后的目录
}
}
然后修改 package.json
里面的 build
命令,设置为从配置文件读取。
"build": "webpack --config webpack.config.js"
我们在打包 webpack 文件的时候,经常会给文件名加哈希后缀,这是为什么呢?
因为浏览器会对上一次的文件做缓存,如果文件名一样的话就会被缓存,然而我们希望打包之后发到线上的文件不要使用缓存,所以就要加上哈希值,保证每次生成的文件名不一样。
也是这个原因,如果我们每次都要在 HTML 文件里面手动引入打包后的 JS 文件,这该多么麻烦。因此,有个叫 html-webpack-plugin 的插件帮我们完美解决这个问题。
我们在 public 文件夹下新建一个 index.html 文件,然后修改 webpack 配置,引入 html-webpack-plugin 插件。
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
mode:'development',
entry: path.resolve(__dirname,'./src/index.js'), // 入口文件
output: {
filename: '[name].[hash:8].js', // 打包后的文件名称
path: path.resolve(__dirname,'./dist') // 打包后的目录
},
plugins:[
new HtmlWebpackPlugin({
template:path.resolve(__dirname,'./public/index.html')
})
]
}
我们已经可以看到生成的文件后面带上了哈希,index.html 也自动引入了这个 JS 文件,但发现每次 build 之后,上次打包的文件还在 dist 文件夹下面。
这样很明显不符合我们的需求,赶紧去找了找。刚好找到一个 clean-webpack-plugin
插件,可以完美解决我们的需求。
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
module.exports = {
plugins:[new CleanWebpackPlugin()] // 引入 CleanWebpackPlugin 插件
}
再执行一次 npm run build
,可以看到前几次生成的文件被清除了。
我们已经可以成功打包 JS 文件,但如果想对 css 文件做解析该怎么办?这里涉及到两个 loader 和一个插件。
css-loader
是将引入的 css 文件打包到 JS 文件里面。
style-loader
是将打包到 JS 文件中的 css 代码解析到 HTML 的 style 标签里面。
mini-css-extract-plugin
是将 css 文件单独打包成 css 文件的一个插件。
我们直接在配置里面增加这些:
module: {
rules: [
{
test:/\.css$/,
use:['style-loader','css-loader'] // 从右往左解析
}
]
},
plugins: [
new MiniCssExtractPlugin({
filename: "[name].[hash].css",
chunkFilename: "[id].css",
})
]
在我们写代码中,经常会用到一些浏览器暂时还不支持的新 ES 语法,为了支持这些新语法,我们需要来配置 Babel。
我们可以添加 babel-loader
和 @babel/preset-env
来支持 ES6/ES7/ES8 等语法。
npm i babel-loader @babel/preset-env @babel/core -D
我们在根目录下创建 .babelrc
文件来编写 babel 的相关配置。
// .babelrc
{
"presets": ["@babel/env"]
}
但是这个只会将我们的 ES6 代码转成 ES5 代码,如果是 ES5 中本来就不支持的 API,比如 Promise、Map 等等,那就没办法转了。
所以是时候使用 polyfill 了,可以使用 babel-plugin-transform-runtime
这个插件来 polyfill 一些新的 API。
安装插件:
npm i @babel/plugin-transform-runtime @babel/runtime -D
修改 .babelrc 配置文件:
{
"plugins": [
"@babel/plugin-transform-runtime"
],
"presets": ["@babel/env"]
}
终于说到了本文的重点了,前面的铺垫工作都已经完成了,那么我们该如何配置 React 的环境呢?
这里依然需要一个 babel 的插件来支持,安装 @babel/preset-react
就可以转换 JSX 语法。
.babelrc 配置文件:
{
"plugins": [
"@babel/plugin-transform-runtime"
],
"presets": ["@babel/env", "@babel/preset-react"]
}
我们将入口的 index.js 换成 index.jsx,写两行 React 代码试试。
import React from 'react';
import ReactDOM from 'react-dom'
function App() {
return (
<div>hello, world</div>
)
}
ReactDOM.render(
<App />,
document.getElementById("app")
)
执行一下 npm run build
,很完美。
我们现在每次 build 生成文件,然后手动在本地运行 HTML 文件。如果之后用到 react-router
,本地打开 HTML 文件就只能用 HashRouter
了,而且我希望能本地启一个服务器,支持热更新。
首先,我们来安装 webpack-dev-server
,它会在本地启动一个服务,将你的文件放到内存里面,也会响应你的修改来做热更新。
npm i webpack-dev-server -D
接着,我们来修改 webpack 的配置,增加热更新配置,这里设置监听 3000 端口。
const webpack = require('webpack')
// webpack.config.js
devServer: {
port: 3000,
hot: true,
contentBase: './dist'
},
plugins: [
new Webpack.HotModuleReplacementPlugin()
]
然后,我们再来修改 package.json 文件,增加 dev
的 script。
"dev": "webpack-dev-server --config webpack.config.js --open"
我们运行一下 npm run dev
,发现会自动打开一个窗口,我们的页面已经跑在了 localhost:3000
上面。
至此,一个完整的 React 环境配置就已经搞定了,我把它放到了 GitHub 上面:webpack-react
当然,如果你不想手动操作那么繁琐的配置,你也可以试试 create-react-app
,这是生成 React 项目配置的一个脚手架。
快速开始:
npx create-react-app my-app
cd my-app
npm start
当你准备部署到生产环境的时候,你可以执行 npm run build
。
如果你想自定义 webpack 的配置,那么可以使用 ejecting
来暴露出 webpack 的配置。
npm run eject
如果你想使用 css-modules
、TypeScript
等等,可以去看官方的详细文档:Create React App 官方文档
由于 Webpack 的繁琐配置,很多开发者都希望有一个配置更简单的打包工具出来,Parcel 就因此诞生了。它利用多核处理提供了极快的速度,并且不需要任何配置。
首先我们来创建一个新的项目:
mkdir parcel-react
cd parcel-react
npm init
然后我们通过 Yarn 或者 npm 来安装 Parcel:
// yarn
yarn global add parcel-bundler
// npm
npm install -g parcel-bundler
当然你也可以安装到项目里面:
npm install parcel-bundler -D
-D 相当于 -dev,-S 相当于 --save
Parcel 一般需要一个入口文件,一般是 HTML 或者 JavaScript 文件,我们这里以 HTML 文件为入口。
接下来安装 React 相关依赖包:
npm install -S react
npm install -S react-dom
npm install -D parcel-bundler
此时 Parcel 相关的依赖已经安装好了。可能你会好奇为什么没有安装 Babel 相关的包呢?这样可以支持 ES6 以及 JSX 的语法吗?
Parcel 里面已经默认安装了 @babel/core
、@babel/preset-env
、@babel/plugin-transform-react-jsx
等包,我们不需要再额外安装。
接下来,我们需要创建一个入口的 HTML 文件,然后在 package.json
的 scripts
里面添加这么一句。
// package.json
"scripts": {
"start": "parcel index.html"
}
然后需要在你的 HTML 文件里面引入你的 .jsx
入口文件,Parcel 会从这个入口文件开始解析。
这样我们就可以用 npm start
的形式来启动项目了。启动项目的时候,Parcel 会默认监听 1234 这个端口号,启动一个类似 webpack-dev-server 的服务。
添加 --open
的参数,会在服务启动后自动帮你打开对应的地址。
parcel index.html --open
如果你想换其他端口,可以在 scripts 里面修改。
parcel index.html --port 3000
当然,Parcel 的配置也许不能满足你的要求,比如我想使用装饰器该怎么办?我想使用类属性怎么办?
Parcel 也允许你手动添加一个 .babelrc
文件,在这个文件里面写上你的配置。
这样一个简单的基于 Parcel 的 React 环境就搭建好了。为了方便大家参考,我这里把配置了 React/Redux 和 React/Mobx 的项目放到了 GitHub。
Parcel-React 项目地址:Parcel-React-Templates
随着前端工程化这一概念深入人心,学会配置 webpack 打包、优化文件是非常重要的,这也是每个前端工程师都应该掌握的知识。