Webpack4.0从零配置一个react开发环境

在过去很长一段时间,我都没有研究 webpack 相关但东西,一方面是现在已经有了很多官方构建工具,另一方面是这些构建工具基本能够完成现在的需求了,作为一个开发人员,应该把更多但经历放到业务上,所以对 webpack 一直都是简单了解,需要使用的时候再查文档.正常情况下,这样做是没有问题的,不需要花费太多的时间和精力就能构建出一个不错的开发环境.

可随着业务(需求)复杂度的提升,官方构建工具有的时候就不能满足我们的需求了,就需要自己去配置.由于之前的项目我曾遇到过这样的需求,短时间内无法用 webpack 配置出一个自己满意的环境,最后是用 gulp 来解决了这样的问题.所以决定更多的学习了解 webpack 的使用,配置一个 react 开发环境只是当作学习后的一个检验.

准备工作

建立项目目录

1.到目标路径下创建目标文件夹

2.进入文件夹后执行 npm init 执行 npm 初始化

安装 webpack

1
npm install --save-dev webpack webpack-cli

因为 webpack 最新的版本是 4.31.0,所以我们需要安装 webpack—cli,另外本地安装 webpack 的原因官方已经有了说明:

对于大多数项目,我们建议本地安装。这可以使我们在引入破坏式变更(breaking change)的依赖时,更容易分别升级项目。

准备项目文件结构

一般我们的 react 开发有 js、html、css 和其他的静态资源,另外为了方便 webpack 配置管理,所以我们把 webpack 配置单独放到一个文件夹里面,如图:
201905171439.png
我们其中 build 是 webpack 位置文件夹,webpack.base.js 是 webpack 的通用配置,webpack.dev.js 和 webpack.prod.js 分别是开发打包配置和发布打包配置.

配置 webpack

基础配置

1.我们先在 public 目录下创建一个模板文件 index.html

1
2
3
4
5
...
<body>
<div id="app"></div>
</body>
...

2.在 src 目录下创建 main.js

1
document.getElementById("app").innerText = "Hello, Webpack!";

3.编辑 build 下的 webpack.base.js

因为我们需要在 html 中注入 js,所以这里需要安装html-webpack-plugin

1
npm install --save-dev html-webpack-plugin
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
const path = require("path");
const htmlWebpackPlugin = require("html-webpack-plugin");

module.exports = {
entry: "./src/main.js",
output: {
filename: "bundle.js",
path: path.resolve("dist"),
},
plugins: [
new htmlWebpackPlugin({
filename: "index.html",
template: "public/index.html",
inject: "body",
}),
],
};

4.打包

1
npx webpack --config ./build/webpack.base.js

npx:Node 8.2+ 版本提供的 npx 命令,可以运行在初始安装的 webpack 包(package)的 webpack 二进制文件

不出意外的话你会发现多了一个 dist 目录,运行 dist 下的 index.html,屏幕上会打印出’Hello, Webpack!’.

5.配置 package.json

这个打包命令这么长,你肯定不想每次都输入这么多,所以我们修改一下 package.json,修改 scripts 为:

1
2
3
4
5
"scripts": {
"dev": "webpack-dev-server --config ./build/webpack.dev.js",
"build": "webpack --config ./build/webpack.prod.js",
"test": "echo \"Error: no test specified\" && exit 1"
},

执行一下 npm run build ,可以看得和上面的打包是一样的.dev 则是开发环境,下面就来配置一下 webpack-dev-server

配置 webpack-dev-server

安装 webpack-dev-server、clean-webpack-plugin

1
npm install --save-dev webpack-merge clean-webpack-plugin webpack-dev-server

编辑 webpack.dev.js

1
2
3
4
5
6
7
8
9
10
11
12
const path = require("path");
const merge = require("webpack-merge");
const webpackBaseConfig = require("./webpack.base");

module.exports = merge(webpackBaseConfig, {
devtool: "inline-source-map",
devServer: {
contentBase: path.join(__dirname, "../dist"),
port: 8080,
open: true,
},
});

运行一下 npm run dev ,浏览器会自动打开,页面上会打印出 Hello,Webpack!,我们修改一下 main.js 里面的内容,保存界面会自动刷新.

使用 react、bable

既然要使用 react,我们先安装 react、react-dom 核心库和 bable-loader

1
2
3
npm install --save react react-dom
// loaders
npm install --save-dev babel-loader @babel/core @babel/preset-env

然后重新编辑 main.js 和 webpack.base.js
main.js

1
2
3
4
import React from "react";
import ReactDom from "react-dom";

ReactDom.render(<div>I'm A React App.</div>, document.getElementById("app"));

webpack.base.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
...
module: {
rules: [
{
test: /\.m?js$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env', '@babel/preset-react'],
}
}
}
]
}
...

重启 webpack-dev-server,顺利的话可以看到屏幕上已经打印出了: I’m A React App.

其他配置

虽然 react 的开发环境已经跑起来了,但还远远不够,我们还没有用到样式表和其他资源.

静态资源

加载 css

加载 css 我们需要 style-loader 和 css-loader,但通常情况下我们还会使用一些 css 预处理如:sass 和 postcss 等,所以还需要安装 sass-loader、node-sass 和 postcss-loader

1
2
3
npm install --save-dev style-loader css-loader sass-loader node-sass postcss-loader
// 因为使用了postcss,所以还需要安装以下postcss常用插件
npm install --save-dev postcss-import postcss-cssnext cssnano autoprefixer

我们在更目录下创建 postcss.config.js

1
2
3
4
5
6
7
8
9
10
module.exports = {
plugins: {
"postcss-import": {},
"postcss-cssnext": {},
cssnano: {},
autoprefixer: {
browsers: ["last 7 iOS versions", "last 3 versions", "> 1%"],
},
},
};

然后重新编辑 webpack.base.js,在 rules 中添加以下代码

1
2
3
4
5
6
7
8
rules: [
...
{
test: /\.scss$/,
use: ['style-loader', 'css-loader', 'postcss-loader', 'sass-loader']
}
...
]

我们修改文件目录,再创建一个 index.scss,随便写点东西并将 scss 引入 main.js,从新运行 npm run dev,发现没有任何变化,这里有一个坑,需要配置 css-loader

1
2
3
4
5
6
7
8
9
10
11
12
13
{
test: /\.scss$/,
use: [
'style-loader',
{
loader: 'css-loader',
options: {
modules: true
}
},
'postcss-loader',
'sass-loader']
}

现在再运行就可以看到文字颜色发生了变化.现在的目录结构如下:
201905221540.png

其他静态资源

但是项目中还存在一些其他的资源,比如图片、字体等,这些我们可以用 file-loader 来处理.在 webpack.base.js 的 rule 中加入

1
2
3
4
5
6
7
8
9
10
11
12
{
test: /\.(png|svg|jpg|gif)$/,
use: [
'file-loader'
]
},
{
test: /\.(woff|woff2|eot|ttf|otf)$/,
use: [
'file-loader'
]
}

输入

由于每次打包生成的 bundle 文件都不一样,都会一直保留,所以我们引入 webpack 清理插件 clean-webpack-plugin

1
npm install clean-webpack-plugin --save-dev

并加入到 webpack.base.js 中

1
new CleanWebpackPlugin(['dist']),

TypeScript

现在项目中使用 ts 的场景越来越多,我们将现在 webpack 添加 typescript 支持 1.安装

1
npm install --save-dev typescript ts-loader @types/react @types/react-dom

2.根目录下创建 tsconfig.json

1
2
3
4
5
6
7
8
9
10
{
"compilerOptions": {
"outDir": "./dist/",
"noImplicitAny": true,
"module": "es6",
"target": "es5",
"jsx": "react",
"allowJs": true
}
}

3.配置 webpack.base.js

修改入口文件、rule 和 reslove

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
...
entry: './src/main.tsx',
module: {
rules: [
{
test: /\.tsx?$/,
use: 'ts-loader',
exclude: /node_modules/
}
]
},
resolve: {
extensions: [ '.tsx', '.ts', '.js' ]
}
...

使用 ts 时需要特别注意以下两点

  1. 当从 npm 安装第三方库时,一定要牢记同时安装这个库的类型声明文件。你可以从 TypeSearch 中找到并安装这些第三方库的类型声明文件。

举个例子,如果想安装 lodash 这个库的类型声明文件,我们可以运行下面的命令:

1

npm install –save-dev @types/lodash

1
2
3
4
5
6
7
8
9
2. 要在 TypeScript 里使用非代码资源,我们需要告诉 TypeScript 如何兼容这些导入类型。那么首先,我们需要在项目里创建 custom.d.ts 文件,这个文件用来编写自定义的类型声明。让我们将 .svg 文件进行声明设置:
custom.d.ts
```typescript

declare module "\*.svg" {
const content: any;
export default content;
}

修改后的 main.tsx

1
2
3
4
5
6
import * as React from "react";
import * as ReactDOM from "react-dom";

import { App } from "./App";

ReactDOM.render(<App />, document.getElementById("app"));

修改后的 App.tsx

1
2
3
4
5
6
7
import * as React from "react";

export class App extends React.Component<{}, {}> {
render() {
return <div>I'm A React App Compiled By TypeScript.</div>;
}
}

运行以下,屏幕上打印出了上面的文字.

这里一定要使用 tsx,ts 语法中写 html 会有很多错误,虽然将类型推断设置为 any 可以忽略这些错误,但这样使用 typescript 还有什么意义呢.

发布&配置生产环境

1.安装 UglifyJSPlugin

1
npm install --save-dev UglifyJSPlugin

2.修改 webpack.prod.js

1
2
3
4
5
6
7
const merge = require("webpack-merge");
const webpackBaseConfig = require("./webpack.base");
const UglifyJSPlugin = require("uglifyjs-webpack-plugin");

module.exports = merge(webpackBaseConfig, {
plugins: [new UglifyJSPlugin()],
});

执行以下 npm run build,不出意外已经成功打包了!

至此,我们完成了 wabpack 从零构建 react 开发环境的任务,但这只是一个开始,webpack 的高级用法还有很多,后续还需努力.

模板地址: https://github.com/qiangqiang93/webpack-template

参考文章: webpack 中文文档 | webpack 中文网
参考文章: 详解 webpack 之 scss 和 postcss-loader 的配置javascript 技巧脚本之家
参考文章: 从零开始使用 webpack(4.x)+bable+react+ant-design 配置单页面应用开发环境(附模板) - 追逐丶的博客 - CSDN 博客

[越努力,越幸运!]