阅读 197

手把手教你用webpack搭建react项目

上篇文章学习了webpack的基础知识,这次就一起动手来搭建一个简单的react工程吧~

首先使用命令行创建一个新工程

mkdir react-demo
cd react-demo
npm init -y // 把所有预置项都配置成npm默认的配置项
复制代码

下来我们安装基础依赖,webpack从4开始就将webpack和webpack-cli分开处理了,所以需要分开安装

npm install react react-dom // 高版本的npm,所以不指定-s参数,也能顺利写入
npm install webpack -D
npm install webpack-cli -D
复制代码

然后我们在工程中新建src文件夹,并在src文件加下创建App.js文件,将该文件挂载在id为app的dom上:

import React from 'react';
import ReactDom from 'react-dom';

const App = () => {
    return (
        <div>
            <h1>React大法好</h1>
        </div>
    )
}

export default App;
ReactDom.render(<App/>, document.getElementById('app'));
复制代码

在src文件夹下创建index.html文件,写入id为app的dom

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>React Webpack测试</title>
</head>
<body>

<div id="app"></div>

</body>
</html>
复制代码

这个时候我们会遇到两个问题

  • const App => {},这是一个ES6语法,webpack只能处理ES5及以下版本的js,所以这时候直接打包会报错
  • html文件在webpack当中应该怎么处理呢?

首先解决第一个问题,如何将ES6语法代码转换成较低版本的ES语法代码,那这个时候就需要引入babel来进行编译

npm install @babel/core @babel/cli
复制代码

在项目中新建一个test.js文件(后期可删除),写一段ES6语法:

[1, 2, 3].map(item => {
    console.log(item);
})
复制代码

然后看看该ES6代码如何变成ES5的代码,命令行输入

babel test.js

// 结果为
// [1, 2, 3].map(item => {
//   console.log(item);
// });

复制代码

那我们引入了babel之后,为什么还是ES6语法的样子呢?原来是因为我们没有加转换规则,我们继续安装转换规则

// preset-env核心语法将高版本ES语法转换成低版本
npm install @babel/preset-env 
复制代码

下面再来试试,此时注意,在进行编译的同时我们需要指定规则

babel test.js --presets=@babel/preset-env

// 结果为
// [1, 2, 3].map(function (item) {
//   console.log(item);
// });
复制代码

看到这时已经成功将ES语法转换成低版本,这里强调一下,babel除了可以用命令行来做配置文件之外,还可以像webpack一样支持配置文件,有以下两种形式:

  1. 可以直接放在package.json里面
"dependencies": {
  "@babel/preset-env": "^7.12.10"
},
"babel": {
  "presets": ["@babel/preset-env"] // 在此处指定规则
}
复制代码
  1. .babelrc的配置文件(react-demo下新建一个.babelrc文件)
{
    "presets": ["@babel/preset-env"]
}
复制代码

以上两种形式是等价的,但是babel在转义的时候会优先去查找.babelrc文件,如果不存在,才会考虑其他的路径。

下面再考虑我们如何在react项目里使用babel呢?要把一种代码编译成另一种代码,是在文件维度的动作,loader正是对文件进行操作,所以我们这里使用loader,在react-demo文件夹下新建webpack.config.js文件:

module.exports = {
    module: {
        rules: [
            {
                test: /\.jsx?/, // 即匹配了js文件又匹配了jsx文件
                 // 将node_modules排除在外,在编译过程中,不仅编译了自己项目代码,还编译node_modules那么多不是自己写的代码,非常不利于webpack构建性能
                exclude: /node_modules/,
                use: {
                    loader: 'babel-loader'
                }
            }
        ]
    }
}
复制代码

此时不仅要对.js文件进行处理,还需要对.jsx文件进行处理,这时就需要安装babel/core、babel/cli、babel-loader

npm install @babel/core @babel/cli -D
npm install babel-loader -D
复制代码

接下来继续配置babel规则

  1. 配置ES6相关规则
  2. 配置.jsx相关规则

然后我们需要安装@babel/preset-env规则的基础上再安装@babel/preset-react 规则

npm install @babel/preset-env @babel/preset-react -D
复制代码

安装完成后,继续在webpack.config.js下配置规则

 module: {
        rules: [
            {
             use: {
                    loader: 'babel-loader',
                    options: {
                        babelrc: false, // 没有babelrc文件
                        presets: [
                            require.resolve('@babel/preset-react'),
                            require.resolve('@babel/preset-env', { modules: false })
                            // modules: false -> 模块化方案的一个指定,在编译ES6语法的时候,是否将import语法当做ES6语法进行编译
                            // webpack识别import和export,因为我们已经有了commonJS这个模块化方案,所以我们可以置为false
                        ],
                        // 是否对编译结果做缓存
                        cacheDirectory: true,
                    }
                }
            }
        ]
    }
}
复制代码

接下来我们处理.html文件:

npm install html-webpack-plugin -D
复制代码

在webpack.config文件中配置如下信息:

const HtmlWebpackPlugin = require('html-webpack-plugin');
const path = require('path');

module.exports = {
  plugins: [
      new HtmlWebpackPlugin({
          template: path.resolve(__dirname, 'src/index.html'), // 需要被处理文件路径
          filename: "index.html" // 文件打包完毕之后,目标文件名称
      })
  ]
}
复制代码

此时我们发现jsx文件只有输出,并没有引入,所以我们.jsx需要入口文件,在src文件夹下新建index.jsx文件

import App from './App';
复制代码

webpack虽然有默认的入口文件,谨慎起见,还是需要写一下入口文件

module.exports = {
    entry: path.resolve(__dirname, 'src/index.jsx'),
}
复制代码

下来打包文件试试,因为我们现在仍处于开发阶段,所以模式设置为development,命令行输入:

webpack --mode development
复制代码

此时可以看到打包成功!之后我们安装webpack-dev-server来启动看看是否成功

npm install webpack-dev-server -D
webpack-dev-server
复制代码

启动项目之后报错了!

最后经过一番查找,我们需要将webpack-cli换到3版本,那这里我们就用3.3.12版本吧,安装之后再试试~

哈哈哈,终于成功了~在启动项目时也可以在package.json文件内配置自定义构建命令

"scripts": {
  "test": "echo \"Error: no test specified\" && exit 1",
  "dev": "webpack-dev-server --mode development --open" // --open 自动打开浏览器
}
复制代码

配置自定义构建命令之后,我们运行npm run dev即可启动项目

做个扩展吧,那该项目如何做到热替换(HMR)?继续在webpack.config.js文件中修改devServer

const webpack = require('webpack');

plugins: [
    new webpack.HotModuleReplacementPlugin()
],
devServer: {
    hot: true
}
复制代码

在入口文件index.jsx内添加

if (module.hot) {
    module.hot.accept(error => {
        if (error) {
            console.log('热替换出bug了');
        }
    })
}
复制代码

重启项目,简单修改一下你的代码,即可看到热更新效果啦~

这个项目比较简单,路由什么的都还没有加,有兴趣的同学后期可以添加呀😊

文章分类
前端
文章标签