1、项目基础需求配置
开始一个最基础的React项目,我们需要如下配置
1.1、react、 react-dom
1.2、Babel
1.3、webpack
因为是写组件库,所以最好也使用typescript
1.4、typescript
2、创建文件夹,初始化npm
2.1、mkdir dragon-react-mobile && cd dragon-react-mobile
2.2、npm init (按照提示填写下一步)
3、安装基础依赖,之后逐渐完善
3.1、npm i react react-dom
3.2、npm i -D webpack
3.3、npm i -D webpack-cli (使用 webpack 4+版本,需要安装 CLI)
4、创建文件夹/基础文件
创建配置文件夹config,添加以下文件
4.1、webpack.dev.config.js (开发环境,本地开发组建使用)
4.2、webpack.prod.config.js (生产环境,打包最后的组件)
4.3、webpack.base.config.js (提出webpack配置的公用部分)
创建src文件夹,添加文件
4.4、index.html 开发环境的页面添加内容
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app"></div>
<script src="../dist/bundle.js"></script>
</body>
</html>
添加App.jsx,内容如下
import React, { Component } from 'react'
export default class App extends Component {
render() {
return (
<div>Hello, World!</div>
)
}
}
4.5、bundle.js 开发环境的出口文件
创建src/components文件夹,存放组件
创建src/entry文件夹 存放入口文件,添加如下文件
4.6、dev_index.js (开发入口)
import React from 'react'
import { render } from 'react-dom'
import App from '../App.jsx'
const renderDom = Component => {
render(
<Component />,
document.getElementById('app')
)
}
renderDom(App)
4.7、prod_index.js (打包入口) 之后在添加,先本地环境启动
根目录添加文件
4.8、 README.md
4.9、.gitinore
此时的目录结构如下
├── config 配置
└── webpack.base.config.js webpack 公用
└── webpack.dev.config.js webpack dev环境
└── webpack.prod.config.js webpack prod环境
├── node_modules
├── src
│ ├── components 组件文件夹
│ │ ├── ...
│ ├── entry 工具方法
│ │ ├── dev_index.js 开发入口
│ │ └── prod_index.js 打包入口
│ ├── App.jsx
│ ├── index.html
│ ├── bundle.js
├── .gitinore
├── package.json
├── package-lock.json
└── README.md
5、开始配置webpack --开发环境
5.1、指定入口entry
5.2、指定出口output(名称和路径)
配置loader,需要先配置babel
5.3、npm install -D babel-loader @babel/core @babel/preset-env @babel/preset-react
依赖说明
babel 的功能在于「代码转译」,具体一点,即将目标代码转译为能够符合期望语法规范的代码。在转译的过程中,babel 内部经历了「解析 - 转换 - 生成」三个步骤。而
@babel/core 这个库则负责「解析」,具体的「转换」和「生成」步骤则交给各种插件(plugin)和预设(preset)来完成。
babel-loader 是一个 npm 包,它使得 webpack 可以通过 babel 转译 JavaScript 代码。
@babel/preset-* 实际上就是各种插件的打包组合,也就是说各种转译规则的统一设定,目的是告诉loader要以什么规则来转化成对应的js版本
@babel/preset env是一个智能预置,它允许您使用最新的JavaScript,而无需对目标环境所需的语法转换(以及可选的浏览器polyfill)进行微观管理。这不仅让您的生活更轻松,而且JavaScript捆绑包更小!(官网解释)
@babel/preset-react:对react语法的转换
5.4、根目录新建.babelrc文件,配置babel,内容如下
{
"presets": ["@babel/preset-env", "@babel/preset-react"]
}
5.5、package.json 添加脚本
"dev": "webpack --config config/webpack.dev.config.js"
5.6、webpack.dev.config.js 内容
const path = require('path')
module.exports = {
mode: 'development',
entry: path.resolve(__dirname, '../src/entry/dev_index.js'), // 指定开发入口文件
output: {
filename: 'bundle.js', // 打包后的文件名称
path: path.resolve(__dirname, '../dist'), // 输出路径
},
module: {
rules: [
{
test: /\.(js|jsx)$/,
use: {
loader: 'babel-loader'
},
exclude: /node_modules/
}
]
}
}
5.7、执行 npm run dev ,打开index.html OK!!! 成功执行
6、搭建服务器
现在已经可以成功了,但是有一个问题,每次修改都需要重新构建刷新index.html才可以,webpack-dev-server 为你提供了一个简单的 web 服务器,并且能够实时重新加载(live reloading)。让我们设置以下:
6.1、npm install --save-dev webpack-dev-server
webpack.dev.config.js 文件添加
devServer: {
contentBase: './src',
},
package.json 修改
"dev": "webpack-dev-server --config webpack.dev.config.js"
修改一下index.html里js 引用路径
<script src="./bundle.js"></script>
执行npm run dev 此时打开index.html 修改App.jsx内容 OK,如果不行,请注意自己index.html位置,或者是入口、出口、contentBase路径,webpack的路径最好都写成绝对路径,本人调试的时候也是多次遇到路径的问题,写文章的时候也许有修改过
这时候有点小缺陷
(1)、index.html 写死的,对于写组件倒也无所谓,对于普通项目肯定不合适,这时候咱们顺便学习一下,做一下修改,使用html-webpack-plugin
(2)、页面是整体刷新,这样体验也不好,使用HMR,模块热替换
6.2、npm install html-webpack-plugin --save-dev
webpack.dev.config.js 文件添加
+ const HtmlWebpackPlugin = require('html-webpack-plugin');
+ plugins: [
new HtmlWebpackPlugin({
template: path.resolve(__dirname, '../public/index.html')
})
]
根目录新建public文件夹,放入index.html,此时删除js引用,重新启动发现ok,当然html-webpack-plugin也可以添加其他配置,这里只做开发使用,暂时不做其他修改
6.3、配置HMR,对于这个项目HMR配置有两个关键点
(1)webpack.config的devServer中配置hot: true
webpack.config的plugins增加HotModuleReplacementPlugin
(2)使用module.hot.accept增加HMR代码
只添加第一个是没有作用的,在入口文件dev_index.js 添加,暂时全部,之后优化
if (module.hot) { //告诉 webpack 接受热替换的模块
module.hot.accept()
}
可能对于之前wabpack的版本或者是用的webpack-hot-middleware方式还需要plugins添加new webpack.HotModuleReplacementPlugin(),这个项目只需要考虑上述两点就行