使用webpack5从0到1搭建一个react项目的实现步骤


Posted in Javascript onDecember 16, 2020

前言

在这之前,每开始一个新项目我都是使用现有的脚手架,这非常便于快速地启动一个新项目,而且通用的脚手架通常考虑地更加全面,也有利于项目的稳定开发;不过对于一个小项目,根据需求自己搭建可能会更好,一方面小项目不需要脚手架那么丰富的功能,另一方面可以提高对项目的掌控度以方便后期的扩展。
这篇文章是在实践中总结的,具有实操性,读者可跟着一步步进行搭建,中间我会穿插一些原理,当然因为笔者的能力有限,不会特别深入。

预备知识

  • 熟悉Javascript && HTML && CSS
  • 熟悉ES6+
  • 有能力搭建Nodejs环境
  • 会用命令行

目标

学习使用webpack5和为什么使用它
用webpack5搭建开发环境
用webpack5搭建生产环境

什么是webpack

这有点老生常谈了,不过为了新同学能够看下去,在这里简单介绍一下。一个现代化的web应用,已经不是单纯地优html、css、javascript组成的,它还需要对应用进行打包、压缩和编译成浏览器能够理解的代码,于是webpack就开始流行起来了。

webpack是一个模块打包器,它可以打包任何东西。你可以在开发时使用最新的Javascript特性或Typescirpt,webpack会将它编译成浏览器支持的代码并压缩它;你还可以在Javascript中导入需要用到的静态资源。

在开发过程中,webpack提供了开发服务器并支持HMR,什么是HMR和怎么配置后面会详细介绍,现在我们只要知道当我们保存代码的时候webpack会帮我们自动重新编译和刷新浏览器。

webpack的能做的远不止这些,这篇文章主要是帮助你熟悉基本概念和如何去配置自己的脚手架。

开始搭建

这篇文章算是一个较为完整的实战教程,目标是搭建一个可用的脚手架,在此基础上可以扩展出更多的功能。
架构需要支持的特性

  • Webpack5
  • 命令行友好提示
  • es6+
  • React
  • Typescript
  • PostCSS + cssnext
  • HMR

安装webpack

新建一个项目,进入项目根目录,创建默认的package.json

yarn init -y

安装webpack和webpack-cli

  • webpack - 模块打包库
  • webpack-cli - 命令行工具
yarn add webpack webpack-cli -D

基础配置

在根目录下新建一个webpack.config.js

Entry

入口文件,webpack会首先从这里开始编译

// webpack.config.js
const path = require('path');

module.exports = {
 entry: {
  app: './src/index.js'
 },
}

Output

定义了打包后输出的位置,以及对应的文件名。[name]是一个占位符,这里是根据我们在entry中定义的key值,即等价于app

module.exports = {
 /* ... */

 output: {
  path: path.resolve(__dirname, './dist'),
  filename: '[name].bundle.js',
 },
}

确保src下有index.js,然后现在可以使用我们的最小化配置进行打包。在package.json中加入以下代码

"scripts": {
 "build": "webpack"
}

运行该命令

yarn run build

可以在命令行中看到打包的结果,并且在根目录下生成了一个dist目录,说明打包成功。

Plugins

插件使webpack具备可扩展性,可以让我们支持更多的功能。

模板文件

当我们构建一个web app的时候,我们需要一个HTML页,然后再HTML中引入Javascript,当我们配置了打包输出的bundle文件是随机字符串时,每次手动更新就特别麻烦,所以最好的方法是可以自动将bundle打包进HTML中。

Html-webpack-plugin - 从模板生成一个HTML文件

安装

yarn add html-webpack-plugin -D

在根目录下新建一个文件public/index.html,内容如下

<!DOCTYPE html>
<html lang="en">
 <head>
  <title><%= htmlWebpackPlugin.options.title %></title>
 </head>

 <body>
  <div id="root"></div>
 </body>
</html>

其中title是读取html-webpack-plugin插件的配置,配置如下

// webpack.config.js

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

module.exports = {
 /* ... */

 plugins: [
  new HtmlWebpackPlugin({
   title: '铁木真大屏展示',
   template: path.resolve(__dirname, './public/index.html'),
   filename: 'index.html',
  }),
 ],
}

现在我们再次运行yarn run build,可以看到dist下多了一个index.html,其中自动插入了标题和script,效果如下

使用webpack5从0到1搭建一个react项目的实现步骤

打包前清除dist

clean-webpack-plugin - 打包前移除/清理 打包目录

安装

yarn add clean-webpack-plugin -D

配置

const path = require('path')

const {CleanWebpackPlugin} = require('clean-webpack-plugin')

module.exports = {
 /* ... */

 plugins: [
  /* ... */
  new CleanWebpackPlugin(),
 ],
}

命令行友好提示

安装

yarn add friendly-errors-webpack-plugin -D

配置

// webpack.config.js
const friendlyErrorsWebpackPlugin = require('friendly-errors-webpack-plugin');

module.exports = {
 plugins: [
  new friendlyErrorsWebpackPlugin(),
 ]
}

Loaders

webpack使用loaders去解析模块,webpack想要去如何理解Javascript、静态资源(图片、字体、css)、转移Typescript和Babel,都需要配置相应的loader规则。

在项目中只有一个HTML和一些Javascript是没什么用的,我们还需要webpack能够做一些事:

  • 将最新的Javascript特性编译成浏览器理解的
  • 模块化CSS,将编译SCSS、cssnext编译成CSS
  • 导入图片、字体等静态资源
  • 使用自己喜爱的框架,如React

Babel

Babel 是一个 JavaScript 编译器,能将 ES6 代码转为 ES5 代码,让你使用最新的语言特性而不用担心兼容性问题,并且可以通过插件机制根据需求灵活的扩展,我们需要先安装以下库

yarn add babel-loader @babel/core -D
  • babel-loader - 使用Babel和webpack转译文件
  • @babel/core - 转译ES2015+的代码

配置如下

// webpack.config.js
module.exports = {
 /* ... */

 module: {
  rules: [
   // JavaScript
   {
    test: /\.m?js$/,
    exclude: /node_modules/,
    use: {
     loader: 'babel-loader',
     options: {
      presets: ['@babel/preset-env'],
     },
    },
   },
  ],
 },
}

在 Babel 执行编译的过程中,会从项目根目录下的配置文件读取配置。在根目录下创建Babel的配置文件babel.config.json

{
 "presets": ["@babel/preset-env"]
}

如果未安装@babel/preset-env需要先安装

yarn add @babel/preset-env -D

图片和字体

解析图片的loader配置

module.exports = {
 /* ... */
 module: {
  rules: [
   // Images
   {
    test: /\.(?:ico|gif|png|jpg|jpeg)$/i,
    type: 'asset/resource',
   },
  ],
 },
}

解析字体文件的loader配置

module.exports = {
 /* ... */
 module: {
  rules: [
   // Fonts and SVGs
   {
    test: /\.(woff(2)?|eot|ttf|otf|svg|)$/,
    type: 'asset/inline',
   },
  ],
 },
}

样式

现在我们希望能够在Javascript中导入CSS,以及将CSS注入DOM,另外还想使用CSS的高级特性,如cssnext,需要依赖一下库

  • css-loader - 解析CSS导入
  • style-loader - 将CSS注入DOM
  • postcss-loader - 用PostCSS处理CSS
    • postcss-preset-env - PostCSS的默认配置
  • postcss - PostCSS 是一个允许使用 JS 插件转换样式的工具。 这些插件可以检查(lint)你的 CSS,支持 CSS Variables 和 Mixins, 编译尚未被浏览器广泛支持的先进的 CSS 语法,内联图片,以及其它很多优秀的功能。
  • postcss-next - PostCSS的插件,可以使用CSS最新的语法

安装

yarn add css-loader style-loader postcss-loader postcss-preset-env postcss postcss-cssnext -D

新建PostCSS配置文件postcss.config.js,配置如下

module.exports = {
 plugins: {
  'postcss-preset-env': {
   browsers: 'last 2 versions',
  },
 },
}

配置loader

// webpack.config.js

module.exports = {
 /* ... */
 module: {
  rules: [
   // CSS, PostCSS, and Sass
   {
    test: /\.(scss|css)$/,
    use: ['style-loader', {
      loader: 'css-loader',
      options: {
       importLoaders: 1,
      },
     }, 'postcss-loader'],
   },
  ],
 },
}

开发环境

让我们从设置配置为开发模式开始,表示当前的配置的配置为开发环境的配置

// webpack.config.js

module.exports = {
 mode: 'development',
 // ...
}

使用source maps

为了在报错的时候更好的追踪代码和给出错误代码出现的地方的提示,我们可以使用source map,配置如下

// webpack.config.js

module.exports = {
 devtool: 'inline-source-map'
 // ...
}

HMR

当我们改动代码时,希望能自动重新编译代码,webpack提供了三种不同的方式:

  • 监听模式
  • webpack-dev-server
  • webpack-dev-middleware

大多数情况,使用的是webpack-dev-server,本文也是使用这个,不过我会顺带介绍一下其它两种方式,大家各取所需。

使用监听模式:

// package.json
{
 "watch": "webpack --watch"
}

执行以下命令

yarn run watch

现在当我们保存代码的时候会自动编译代码,刷新浏览器后即可看到效果;但是我们想要自动刷新浏览器怎么办,这时候就轮到webpack-dev-server商场了。

webpack-dev-server

它为我们提供了一个服务器和live relaoding的能力,我们需要首先安装它

yarn add webpack-dev-server -D

然后配置如下

// webpack.config.js
module.exports = {
 // ...
 devServer: {
  historyApiFallback: true,
  contentBase: path.join(__dirname, './dist'),
  open: false,
  hot: true,
  quiet: true,
  port: 8082,
 },
}
// package.json
{
 "scripts": {
  "start": "webpack serve"
 }
}

我们在8082端口监听了一个服务,监听的目录是dist,并且支持HMR,现在打开http://localhost:8082,可以看到我们的页面,然后改动代码,浏览器会自动刷新更新效果,是不是很酷!

上面提到了HMR,它的全称是Hot Module Replacement,翻译过来就是热模块替换,我认为它是webpack提供的最有用的一个特性,它允许我们只更新改动过的模块,而不需有全部更新,我们在上面已经开启了该功能,即hot: true。

webpack-dev-middleware

这是一个webpack的中间件,可以让webpack把文件交给一个服务器处理,比如接下来要使用的express,这给了我们更多的控制权,接下来简单演示一下。

安装express和webpack-dev-middleware

yarn add express webpack-dev-middleware -D

更改配置

module.exports = {
 //...
 output: {
  //...
  publicPath: '/'
 }
}

publicPath可以定义了express监听服务的路径,接下来就创建我们的express`服务器

新建一个server.js

const express = require('express');
const webpack = require('webpack');
const webpackDevMiddleware = require('webpack-dev-middleware');

const app = express();
const config = require('./webpack.config.js');
const compiler = webpack(config);

// Tell express to use the webpack-dev-middleware and use the webpack.config.js
// configuration file as a base.
app.use(
 webpackDevMiddleware(compiler, {
  publicPath: config.output.publicPath,
 })
);

// Serve the files on port 3000.
app.listen(3000, function () {
 console.log('Example app listening on port 3000!\n');
});

监听端口为3000,执行以下命令启动服务

node server.js

方便起见,可以将该命令加入package.json

{
 //...
 "scripts": {
  "server": "node server.js"
 }
}

使用Typescript

安装依赖

yarn add typescript ts-loader -D

在根目录下创建typescript的配置文件tsconfig.json,具体配置如下

{
 "compilerOptions": {
  "outDir": "./dist/",
  // "rootDir": "./src",
  "sourceMap": true, // 开启sourcemap
  "module": "commonjs",
  "target": "es5",
  "jsx": "react",
  "esModuleInterop": true,
  "allowJs": true,
  "strict": true
 }
}
// webpack.config.js
module.exports = {
 //...
 module: {
  rules: [
    {
    test: /\.tsx?$/,
    use: 'ts-loader',
    exclude: /node_modules/,
   },
  ]
 }
}

使用React

在上面配置typescript中,已经开启了支持react,现在只需安装react的依赖即可

yarn add react react-dom @types/react @types/react-dom

然后将入口文件改成.tsx后缀,内容如下

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

import './index.css';

const App = () => {
 return <div>hello world2</div>;
};

ReactDOM.render(<App />, document.getElementById('root'));

代码规范

Prettier

Prettier是一个诞生于2016年就迅速流行起来的专注于代码格式化的工具。出道即巅峰啊-.-
Prettier只关注格式化,并不具有lint检查语法等能力。它通过解析代码并匹配自己的一套规则,来强制执行一致的代码展示格式。
它在美化代码方面有很大的优势,配合ESLint可以对ESLint格式化基础上做一个很好的补充。

使用

以VSCode为例,安装Prettier插件即可使用,如果想自定义配置,可以cmd+,快捷键进入vscode配置,搜索Prettier找到对应的配置项进行配置。

Eslint

ESLint 是一个在 JavaScript 代码中通过规则模式匹配作代码识别和报告的插件化的检测工具,它的目的是保证代码规范的一致性和及时发现代码问题、提前避免错误发生。

ESLint 的关注点是代码质量,检查代码风格并且会提示不符合风格规范的代码。除此之外 ESLint 也具有一部分代码格式化的功能。

安装依赖,方便起见,直接使用已有的Eslint配置,这里使用的是fabric

yarn add @umijs/fabric -D

根目录下新建.eslintrc.js,配置如下

module.exports = {
 extends: [require.resolve('@umijs/fabric/dist/eslint')],
 globals: {},
 plugins: ['react-hooks'],
 rules: {
  'no-restricted-syntax': 0,
  'no-param-reassign': 0,
  'no-unused-expressions': 0,
 },
};

重启编辑器,即可应用Eslint的配置。

总结

到目前为止,我们搭建了一个简易的react脚手架,并且它支持typescript、cssnext、HMR等特性,对于一个小项目来说已经足够用了,大家可以在此基础上进行扩展;后面有时间的话会和大家一起讨论一下webpack稍底层的原理,是从源码的角度去看。

附录

how-to-use-webpack
webpack官网

 到此这篇关于使用webpack5从0到1搭建一个react项目的实现步骤的文章就介绍到这了,更多相关webpack5搭建react项目内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Javascript 相关文章推荐
通过JAVASCRIPT读取ASP设定的COOKIE
Nov 24 Javascript
语义化 H1 标签
Jan 14 Javascript
用js遍历 table的脚本
Jul 23 Javascript
回车直接实现点击某按钮的效果即触发单击事件
Feb 27 Javascript
jQuery中用dom操作替代正则表达式
Dec 29 Javascript
JQuery 两种方法解决刚创建的元素遍历不到的问题
Apr 13 Javascript
基于Bootstrap实现的下拉菜单手机端不能选择菜单项的原因附解决办法
Jul 22 Javascript
完美解决jQuery符号$与其他javascript 库、框架冲突的问题
Aug 09 Javascript
微信小程序 欢迎页面的制作(源码下载)
Jan 09 Javascript
vuejs+element UI点击编辑表格某一行时获取内容填入表单的示例
Oct 31 Javascript
vuex存储复杂参数(如对象数组等)刷新数据丢失的解决方法
Nov 05 Javascript
在Vue中使用mockjs代码实例
Nov 25 Vue.js
CentOS 8.2服务器上安装最新版Node.js的方法
Dec 16 #Javascript
原生JS实现拖拽功能
Dec 16 #Javascript
vue图片裁剪插件vue-cropper使用方法详解
Dec 16 #Vue.js
vue实现图片裁剪后上传
Dec 16 #Vue.js
Vue-router中hash模式与history模式的区别详解
Dec 15 #Vue.js
JS创建自定义对象的六种方法总结
Dec 15 #Javascript
npm全局环境变量配置详解
Dec 15 #Javascript
You might like
关于PHP结束标签的使用细节探讨及联想
2013/03/04 PHP
php结合ACCESS的跨库查询功能
2015/06/12 PHP
PHP析构函数destruct与垃圾回收机制的讲解
2019/03/22 PHP
关于Javascript 的 prototype问题。
2007/01/03 Javascript
javascript实现的动态文字变换
2007/07/28 Javascript
基于jquery的一个图片hover的插件
2010/04/24 Javascript
jQuery ajax BUG:object doesn't support this property or method
2010/07/06 Javascript
JavaScript对象创建及继承原理实例解剖
2013/02/28 Javascript
jquery indexOf使用方法
2013/08/19 Javascript
node.js中watch机制详解
2014/11/17 Javascript
javascript实现左右控制无缝滚动
2014/12/31 Javascript
jQuery事件绑定方法学习总结(推荐)
2016/11/21 Javascript
Vue-router 切换组件页面时进入进出动画方法
2018/09/01 Javascript
vue加载完成后的回调函数方法
2018/09/07 Javascript
微信小程序开发(一):服务器获取数据列表渲染操作示例
2020/06/01 Javascript
[08:42]DOTA2每周TOP10 精彩击杀集锦vol.2
2014/06/25 DOTA
[48:37]EG vs OG 2018国际邀请赛小组赛BO2 第一场 8.17
2018/08/18 DOTA
[52:41]OG vs IG 2018国际邀请赛小组赛BO2 第二场 8.18
2018/08/20 DOTA
Python3搜索及替换文件中文本的方法
2015/05/22 Python
Python中断言Assertion的一些改进方案
2016/10/27 Python
全面分析Python的优点和缺点
2018/02/07 Python
sklearn-SVC实现与类参数详解
2019/12/10 Python
Python如何根据时间序列数据作图
2020/05/12 Python
在pycharm中文件取消用 pytest模式打开的操作
2020/09/01 Python
Python JSON常用编解码方法代码实例
2020/09/05 Python
python单例模式的应用场景实例讲解
2021/02/24 Python
html5模拟平抛运动(模拟小球平抛运动过程)
2013/07/25 HTML / CSS
小学安全教育月活动总结
2014/07/07 职场文书
2014年团支部年度工作总结
2014/12/24 职场文书
成绩报告单家长评语
2014/12/30 职场文书
2015年八一建军节演讲稿
2015/03/19 职场文书
可可西里观后感
2015/06/08 职场文书
单身证明格式样本
2015/06/15 职场文书
2016暑期社会实践新闻稿
2015/11/25 职场文书
python实现简易自习室座位预约系统
2021/06/30 Python
nginx sticky实现基于cookie负载均衡示例详解
2022/12/24 Servers