基于webpack的React项目搭建
Posted Raion
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了基于webpack的React项目搭建相关的知识,希望对你有一定的参考价值。
前言
前面我们已经搭建了基础环境,现在将开发环境更完善一些。
-
devtool
在开发的过程,我们会经常调试,so,为了方便我们在chrome中调试源代码,需要更改webpack.config.js,然后启动webpack-dev-server。完成之后在chrome浏览器中打开debug,点击Sources选项,即可看见提示,继而输入你想查看的源文件名即可显示该文件源代码,如果你觉得某处代码有问题,对应行号打上断点即可调试。
...... module.exports = { devtool: \'cheap-module-eval-source-map\', ...... }
-
热更新(HMR)
HMR应该是webpack令人非常兴奋的一个特点,它在代码修改后重新打包并发送到浏览器,浏览器将获取的新模块替换老模块,在不刷新浏览器的情况下实现对应用的更新。由于我们使用的是webpack-dev-server,它提供了两种自动刷新方式供我们选择,iframe和inline模式。这里我们选择inline模式,更改dev-server.js。
......
const server = new WebpackDevServer(compiler, { contentBase: path.resolve(__dirname, \'../build\'), // 默认会以根文件夹提供本地服务器,这里指定文件夹 inline: true, // 自动刷新 hot: true, // 开启热模块替换
......
更改webpack.config.js
......
const webpack = require(\'webpack\');
module.exports = { devtool: \'cheap-module-eval-source-map\', entry: [
\'webpack-dev-server/client?http://localhost:9090\', \'webpack/hot/only-dev-server\', path.resolve(__dirname, \'../src/index.js\') ],
...... plugins: [ new webpack.HotModuleReplacementPlugin()
...... ]
最后更改index.js
import React from \'react\'; import { render } from \'react-dom\'; import App from \'./App\' const renderDom = Component => { render( <Component />, document.getElementById(\'app\') ); } renderDom(App); if (module.hot) { module.hot.accept(\'./App\', () => { const App = require(\'./App\').default; renderDom(App); }) }
接下来执行npm run dev,查看浏览器,发现如下就实现了热更新。
然后修改App.js里render返回的html,保存后可以发现浏览器会自动刷新并看到你更改后的效果。也许这样就实现了React组件的热更新,Right ?我们对App.js做如下更改看看会有什么变化。
import React, { Component } from \'react\'; export default class App extends Component { constructor(props) { super(props); this.state = { count: 1, } } add () { this.setState({ count: this.state.count + 1 }); }; render() { return ( <div> <h1>{this.state.count}</h1> <button onClick={() => this.add()}>增加1</button> </div> ); } }
然后在浏览器中点击按钮,页面中数值随之增加。然后,我们修改一下App.js(在button标签下增加其他标签),保存后浏览器自动刷新。我们查看一下浏览器,那么问题来了,刚刚点击增加后的数值不见了,又回到了初始值1。这时候发现组件的状态并没有保存下来,没有达到真正意义上的React热更新。所以这里还需要引入一个插件,来帮我们解决热更新组件状态保存问题。这也是react-hot-loader的由来。
npm install react-hot-loader --save-dev npm install babel-polyfill --save
更改webpack.config.js。
......
module.exports = { devtool: \'cheap-module-eval-source-map\', entry: [ \'babel-polyfill\', \'react-hot-loader/patch\', \'webpack-dev-server/client?http://localhost:8080\', \'webpack/hot/only-dev-server\',
......
更改index.js。
......
import { AppContainer } from \'react-hot-loader\'; import \'babel-polyfill\'; import App from \'./App\'; const renderDom = Component => { render( <AppContainer> <Component /> </AppContainer>, document.getElementById(\'app\') ); };
......
更改.babelrc。
{ "presets": [ [ "es2015", { "module": false } ], "react" ], "plugins": [ "react-hot-loader/babel"] }
修改完后,需要重新执行npm run dev。我们重复上面的操作,可以发现,没有再出现上面的问题。当然上面的React函数绑定还有多种写法:
//方式一 <button onClick={() => this.add()}>增加1</button> //方式二 <button onClick={this.add.bind(this)}>增加1</button> //方式三,官方推荐使用 constructor(props) { super(props) this.add = this.add.bind(this); } <button onClick={this.add)}>增加1</button> //方式四,推荐(由于处于草案阶段,所以是以插件的方式使用)
add = () => {
......
} <button onClick={this.add)}>增加1</button>
我更倾向于第四种,更简洁。这里我们配置一下第四种方式。
npm install babel-preset-stage-1 --save
最后修改.babelrc即可。
......
"react", "stage-1"
......
-
ESLint语法校验
一个javascript语法检测工具,可以像IDE一样静态检测代码错误并提示。首先安装eslint和eslint-loader。
npm install eslint eslint-loader --save-dev
修改webpack.config.js。
......
module: { rules: [ { enforce: "pre", test: /\\.(js|jsx)$/, loader: \'eslint-loader\', exclude: /node_modules/ },
......
项目根目录下新建.eslintrc.json。
{ "rules": { } }
我们先不创建规则,直接运行会报error Parsing error: The keyword \'import\' is reserved,因为项目中使用了es6等新语法,而这些还不能被直接识别,所以还需安装babel-eslint进行转义。
npm install babel-eslint --save-dev
修改.eslintrc.json文件。
{ "parser": "babel-eslint", "rules": { } }
上述修改完后,就可以重新运行了。到这里,我们可以开始自定义规则,你可以将自己的规则开源出来供大家一起使用。然而要从头到尾全部自定义规则并不切合实际,所幸已经有很多符合最佳实践的规则。这里我们选择Airbnb,安装eslint-config-airbnb(推荐)。
npm install eslint-config-airbnb --save-dev
eslint-config-airbnb需要下面3个插件的支持:
npm install eslint-plugin-import eslint-plugin-jsx-a11y eslint-plugin-react --save-dev
修改.eslintrc.json,暂时加入以下规则。
{ "parser": "babel-eslint", "extends": "airbnb", "env": { "browser": true, "node": true, "es6": true }, "parserOptions": { "ecmaVersion": 6, "sourceType": "module", "ecmaFeatures": { "jsx": true } }, "plugins": [ "react" ], "rules": { "react/jsx-no-bind": [ "error", { "ignoreRefs": true, "allowArrowFunctions": true, "allowBind": true } ], "import/no-extraneous-dependencies": "off", "react/jsx-filename-extension": "off" } }
配置好后重新运行,发现红了一片(很多错)。别急,我们一步一步修改。首先修改index.js,在文件头部加上/*eslint-disable*/,不对index.js进行校验。剩余的我们就不一一更改了,可以让IDE(Webstorm)为我们修改。选择WebStorm的Preferences,搜索ESLint,将我们创建的规则应用到项目中。
然后在报错的文件中,点击红色感叹号,点击第一项,即可自动修改错误。
-
其他常用加载器
其他常用加载器还有很多,这里简单将css配置了一下,其余就不一一配置介绍了,请自行按需配置。最后webpack.config.js配置如下。
css-loader: 解析css代码
style-laoder: 将编译后css样式导入到html中
less-loader: 加载和转移less文件
raw-loader: 加载文件原始内容(utf-8格式)
url-loader: 多用于加载图片
file-loader: 打包文件
const path = require(\'path\'); const webpack = require(\'webpack\'); const HtmlWebpackPlugin = require(\'html-webpack-plugin\'); module.exports = { devtool: \'cheap-module-eval-source-map\', entry: [ \'babel-polyfill\', \'react-hot-loader/patch\', \'webpack-dev-server/client?http://localhost:9090\', \'webpack/hot/only-dev-server\', path.resolve(__dirname, \'../src/index.js\'), ], // 指定入口文件,程序从这里开始编译,__dirname当前目录, ../表示上一级目录, ./同级目录 output: { path: path.resolve(__dirname, \'../dist\'), // 输出的路径 filename: \'app/[name]_[hash:8].js\', // 打包后文件 }, module: { rules: [ { enforce: \'pre\', test: /\\.(js|jsx)$/, loader: \'eslint-loader\', exclude: /node_modules/, }, { test: /\\.(js|jsx)$/, loader: \'babel-loader\', // 加载器 exclude: /node_modules/, }, { test: /\\.css$/, use: [{ loader: \'style-loader\' }, { loader: \'css-loader\' }], }, { test: /\\.less$/, use: [{ loader: \'style-loader\', }, { loader: \'css-loader\', }, { loader: \'less-loader\', options: { sourceMap: true, }, }], }, ], }, plugins: [ new webpack.HotModuleReplacementPlugin(), new HtmlWebpackPlugin({ template: path.resolve(__dirname, \'../src/index.template.html\'), inject: true, }), ], };
以上是关于基于webpack的React项目搭建的主要内容,如果未能解决你的问题,请参考以下文章
基于 Webpack 4 和 React hooks 搭建项目