导航
导航
文章目录
  1. 版本
    1. 快速浏览:
  2. webpack核心概念
  3. 基础配置
    1. 1、初始化项目
    2. 2、安装webpack
    3. 3、HtmlWebpackPlugin
    4. 4、配置转义ES6/ES7/JSX
    5. 5、配置转义Typescript
    6. 6、CleanWebpackPlugin
    7. 7、source-map
    8. 8、WebpackDevServer
    9. 9、编译css和scss并使用css-modules
    10. 10、集成postcss
    11. 11、图片处理
    12. 12、字体文件处理
  4. 测试React环境

动手搭建react开发环境一

前言:接触webpack从在学校的那会起,也一直在使用它,用的都是别人封装好的,偶尔去修改一点点配置,也没有真正自己从零开始配置一个脚手架,接下来几篇将记录我对webpack以及开发中提升效率的配置,其中遇到的一些坑也会提示出来。

版本

  • webpack 4
  • Babel 7

本篇主要使用webpack搭建基础的React环境

快速浏览:

webpack核心概念

  • entry: 入口起点
  • output: 输出
  • module: 模块,webpack中一切皆是模块
  • loader: 转换工具,webpack 只能理解 JavaScript 和 JSON 文件。loader 让 webpack 能够去处理其他类型的文件,并将它们转换为有效模块,以供应用程序使用,以及被添加到依赖图中
  • plugin: 扩展插件,loader 用于转换某些类型的模块,而插件则可以用于执行范围更广的任务,在webpack构建流程中的特定时机注入扩展逻辑来改变构建结果或做你想要做的事情,比如:打包优化,资源管理,注入环境变量等等
  • mode: webpac的打包环境[development, production]
  • chunk: 代码库,一个chunk由十多个模块组合而成,用于代码合并与分割

基础配置

1、初始化项目

1
2
3
4
mkdir webpack-template
cd webpack-template
mkdir src public build dist
npm init -y

2、安装webpack

1
2
3
yarn add webpack webpack-cli -D
cd build
touch webpack.config.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// 简单的webpack配置
// webpack.config.js初始化内容
const path = require('path');

module.exports = {
mode: "development", // 指定环境
entry: ["./src/index.js"], // 打包入口文件
output: {
// 输出目录
path: path.resolve(__dirname, "../dist"),
// 文件名称
filename: "bundle.js"
}, // 打包输出到 dist/bundle.js.
module:{},
plugins:[]
}

package.json更改

1
2
3
"scripts": {
"start": "webpack --config ./build/webpack.config.js"
},

3、HtmlWebpackPlugin

将打包的js自动插入到 index.html 里面去。

1
2
3
yarn add html-webpack-plugin -D
cd public
touch index.html
1
2
3
4
5
6
7
8
9
10
11
12
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Webpack Template</title>
</head>
<body>
<div id="root"></div>
</body>
</html>
1
2
3
4
5
6
7
8
9
10
11
const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
//...同上
plugins:[
new HtmlWebpackPlugin({
filename: 'index.html', // 最终创建的文件名
template: path.join(__dirname, '../public/index.html'), // 指定模板路径
}),
]
}

4、配置转义ES6/ES7/JSX

1
2
3
4
5
6
7
8
// @babel/polyfill: 模拟一个es6+的环境,提供es6方法和函数的垫片
// core-js@2:@babel/preset-env实现按需引入polyfill时,声明core-js版本
yarn add @babel/polyfill core-js@2

// babel-loader和@babel/core是核心模块
// @babel/preset-env是一个智能预设,允许您使用最新的JavaScript
// @babel/preset-react 转换JSX
yarn add babel-loader @babel/core @babel/preset-env @babel/preset-react @babel/plugin-proposal-class-properties -D
1
2
3
4
5
6
7
8
9
10
11
12
module.exports = {
//...同上
module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
use: 'babel-loader',
}
],
},
}

新建.babelrc文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
{
"presets": [
[
"@babel/preset-env", // 将es6的语法翻译成es5语法
{
"useBuiltIns": "usage", // 做@babel/polyfill补充时,按需补充,用到什么才补充什么
"corejs": 2
},
],
"@babel/preset-react"
],
"plugins": [
"@babel/plugin-proposal-class-properties"
]
}

🔥Tip1 问题:Support for the experimental syntax ‘classProperties’ isn’t currently enabled

yarn add @babel/plugin-proposal-class-properties 并在plugins中配置

🔥Tip2 提示:useBuiltIns 和 transform-runtime 不能同时使用,如果使用transform-runtime就不要配useBuiltInsor,一般独立的类库项目才用transform-runtime

5、配置转义Typescript

1
yarn add typescript ts-loader -D
1
2
3
4
5
6
7
8
9
10
11
12
module.exports = {
//...同上
module: {
rules: [
{
test: /\.tsx?$/,
exclude: /node_modules/,
loader: "ts-loader"
}
],
},
}

新建tsconfig.json

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
{
"compilerOptions": {
"baseUrl": ".",
"rootDir": ".",
"outDir": "dist",
"module": "esnext", // 模块引入的方式
"target": "es6", // 转换为es6
"lib": ["dom", "es7"],
"jsx": "preserve",
"moduleResolution": "node",
"sourceMap": true,
"allowJs": true, // 在typescript中允许引入js文件
"forceConsistentCasingInFileNames": true,
"noImplicitReturns": true,
"noImplicitThis": true,
"noImplicitAny": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"strictNullChecks": true,
"importHelpers": true,
"suppressImplicitAnyIndexErrors": true,
"experimentalDecorators": true,
"downlevelIteration": true,
"allowSyntheticDefaultImports": true,
"paths": {
"@/*": ["src/*"]
}
},
"exclude": ["node_modules", "dist", "build", "mock"]
}

6、CleanWebpackPlugin

清除 dist 目录下旧版本文件。

1
yarn add clean-webpack-plugin -D
1
2
3
4
5
6
7
8
9
const { CleanWebpackPlugin } = require('clean-webpack-plugin');

module.exports = {
//...同上
plugins:[
//...同上
new CleanWebpackPlugin()
]
}

7、source-map

可以帮助我们定位到错误信息位置的文件

1
2
devtool: "cheap-module-eval-source-map",  // development
devtool: "cheap-module-source-map", // production

8、WebpackDevServer

webpack在本地为搭建了一个静态文件服务器,实时打包重加载修改的代码。

1
yarn add webpack-dev-server -D
1
2
3
4
5
6
7
8
9
10
11
12
13
14
module.exports = {
//...同上
devServer: {
hot: true,
contentBase: path.resolve(__dirname, "../dist"),
host: "localhost",
port: 8586,
historyApiFallback: true, // 该选项的作用所有的404都连接到index.html
proxy: {
// 代理到后端的服务地址
// "/api": "http://localhost:3000"
}
}
}

修改package.json命令

1
2
3
4
// package.json
"scripts": {
"start": "webpack-dev-server --config ./build/webpack.config.js",
},

9、编译css和scss并使用css-modules

1
yarn add css-loader style-loader sass-loader node-sass -D
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
module.exports = {
//...同上
module: {
rules: [
{
test: /\.(sc|sa|c)ss$/,
use: [
'style-loader',
{
loader: 'css-loader',
options: {
modules: {
localIdentName: '[local]_[hash:base64:5]',
},
// sourceMap: !isDev && true,
},
},
'sass-loader', // 编译scss
],
},
],
},
}

🔥Tip3 问题:当在 css-loader 配置上 sourceMap 时,配合热加载样式会闪屏

sourceMap: !isDev && true,

10、集成postcss

为css某些特性自动增加前缀,并做一些兼容处理。

1
yarn add postcss-loader postcss-preset-env -D
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
module.exports = {
//...同上
module: {
rules: [
{
test: /\.(sc|sa|c)ss$/,
use: [
//...同上
'postcss-loader', // 使用 postcss 为 css 加上浏览器前缀
'sass-loader',
],
},
],
},
}

新建postcss.config.js文件

1
2
3
4
5
6
module.exports = {
loader: 'postcss-loader',
plugins: {
'postcss-preset-env': {},
}
}

新建.browserlistrc文件

1
2
3
4
1% in CN
android >= 4.4
ios >= 8
not ie <= 11

11、图片处理

1
2
3
yarn add file-loader url-loader -D
# file-loader 解决css等文件中引入图片路径的问题
# url-loader 当图片较小的时候会把图片BASE64编码,大于limit参数的时候还是使用file-loader 进行拷贝
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
module.exports = {
//...同上
module: {
rules: [
{
test: /\.(png|jpg|jpeg|gif|svg)/,
use: {
loader: 'url-loader',
options: {
outputPath: 'images/',
limit: 10 * 1024,
},
},
},
],
},
}

12、字体文件处理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
module.exports = {
//...同上
module: {
rules: [
{
test: /\.(eot|woff2?|ttf|svg)$/,
use: [
{
loader: 'url-loader',
options: {
name: '[name]-[hash:5].min.[ext]',
limit: 5000,
publicPath: 'fonts/',
outputPath: 'fonts/',
},
},
],
},
],
},
}

到这里,webpack的基本配置我们已经准备的差不多了,赶紧写点react来试试水。

测试React环境

1
yarn add react react-dom react-router react-router-dom
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// src/index.js
import React, { PureComponent } from 'react';
import ReactDOM from 'react-dom';

export default class App extends PureComponent {
render() {
return (
<div>
hello word~
</div>
)
}
}

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

执行 npm start ,如果页面上能正常显示 hello word~ 那表示我们的webapck基础配置成功。

第一篇webpack基础配置到此结束了,下一篇对webpack进行优化配置。