没有webpack配置项目经验的同学,可以先看以下两篇文章
(1.)https://segmentfault.com/a/11...【基础配置1】
(2.)https://segmentfault.com/a/11...【应用配置2】
写在前面
之前一直都是在帮别人做react的项目,所以并没有去详细了解如果去通过webpack搭建一个react项目,再加上ts项目也是未自己从零开始配置过,刚好最近有时间就配置了一下,发现刚开始还是会对配置有很多疑惑和踩一些小坑
如:
- typescript + react项目
eslint
该怎么配置。 - typescript + react 如何配置
babel
。 - React
cssModules
怎么配置。 - 以及配置antd时
babel.confg
和tsconfig
需要怎么支持。
因为并不是项目使用,所以这里没有去研究如何对打包做优化,感觉应该跟vue的项目差不多是一样的。图片文字处理的话也可以看基础配置,应该也是差不多的
常规配置
本项目都是将开发环境,生产环境分成不同的文件配置而执行的(分离一向是一件比较美好的事。)以下是文件的作用
webpack.config.js
打包时执行文件
-
webpack.common.js
公共的配置文件 -
webpack.dev.js
开发环境配置文件 -
webpack.prd.js
生产环境配置文件
安装相关依赖
npm install webpack webpack-cli webpack-dev-server webpack-merge html-webpack-plugin clean-webpack-plugin cross-env --save-dev
主要配置入口和出口和以及prd与dev的公共插件和module
const path = require('path');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
module.exports = {
entry: {
app: path.resolve(__dirname, '../src/index.tsx')
},
output: {
filename: '[name].[chunkhash].js',
path: path.resolve(__dirname, '../dist'),
chunkFilename: '[name].[chunkhash].js'
},
resolve: {
extensions: ['.tsx', '.ts', '.js']
},
plugins: [
new CleanWebpackPlugin({
cleanOnceBeforeBuildPatterns: [path.resolve(__dirname, '../dist')]
}),
]
}
配置webpack.dev.js
主要包含起node服务,以及区分与生产环境相关的配置。
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
devServer: {
port: 3000,
host: 'localhost',
contentBase: path.resolve(__dirname, 'dist')
},
devtool: 'cheap-module-eval-source-map',
plugins: [
new HtmlWebpackPlugin({
title: '风',
template: path.resolve(__dirname, '../page/index.html'),
minify: {
collapseWhitespace: true,
hash: true,
chunksSortMode: 'manual'
}
}),
],
mode: 'development'
}
配置webpack.prd.js
生产环境'production'相关配置
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
devtool: "cheap-module-source-map",
plugins: [
new HtmlWebpackPlugin({
title: '风',
template: path.resolve(__dirname, '../page/index.html'),
minify: {
collapseWhitespace: true,
hash: true,
chunksSortMode: 'manual'
}
})
],
mode: 'production'
}
配置webpack.config.js
webpack 执行主文件
const merge = require('webpack-merge');
const common = require('./build/webpack.common');
const dev = require('./build/webpack.dev');
const prd = require('./build/webpack.prd');
module.exports = mode => {
if(mode === 'production') {
return merge(common, prd)
}
return merge(common, dev)
}
配置npm script
配置 npm 脚本命令(通过--env development向webpack.config.js函数传入参数)
"scripts": {
"start": "webpack-dev-server --env development --open",
"prd": "webpack --env production"
},
通过以上能够基本起动一个开发环境了,和通过build能生成一个dist目录文件。
配置typescript
在配置typescript的时候我们需要知道typescript是什么,这很重要!在学习过typescript之后我们有了以下的认知:
-
typescript
文件将js文件修改为.ts后缀。 -
typescript
在js基础上多了一些类型约束。 -
typescript
会在编译的时候会根据tsconfig.json
的配置进行检查。 -
typescript
能够在不配置babel的时候通过配置tsconfig.json
支持es6
语法。 -
typescript
使我们写代码的时候更严谨了。(这与后面将到的配置无关)
既然将.js
修改为了.ts
后缀肯定loader
是必然不可少的东西,以及配置ts.confing.json
配置ts-loader
安装依赖:
npm install --save-dev babel-loader typescript ts-loader
在webapck.common.js
文件添加以下配置, 以将ts文件和tsx编译成浏览器认识的文件
module: {
rules: [
{
test: /\.(ts|tsx)?$/,
use: [
'babel-loader',
'ts-loader'
],
exclude: /node_modules/
}
]
}
配置ts.config.json
tsconfig
文件主要配置包含以下几项:
-
compilerOptions
主要是一系列编译选项, 平时配得比较多的一般就target
,module
,allowSyntheticDefaultImports
,strict
,baseUrl
,outDir
,sourceMap
,jsx
这些项,至于这些选项的具体作用,可以查看https://www.tslang.cn/docs/ha... -
exclude
去除node_modules
-
include
设置为[src/**/*
]
这是我的tsconfig配置
{
"compilerOptions": { // 编译配置
"sourceMap": true,
"noImplicitAny": true,
"module": "ESNext",
"target": "es5",
"jsx": "react",
"strict": true,
"allowSyntheticDefaultImports": true,
"moduleResolution": "node" // 解决按需引入antd 报错问题(module设置为ESNext)
},
"exclude": [ // 不检查以下文件内容
"node_modules"
],
"include": [ // 检查以下文件内容
"src/**/*",
"postcss.config.js"
]
}
配置babel
babel
主要作用是将ECMAScript2015+ 版本的代码转为向后兼容的javascript
代码。如果没配置过babel
可以推荐去看下地址,如果想更深入可以去阅读一遍官方文档babel-中文网.
babel配置列表
-
presets
预设。 如果不需要自己手动组合插件就可以选择配置presets
相关插件。
数组结构,执行从后往前执行。
-
plugins
插件。
安装插件:(@babel/core)是必须的npm install --save-dev @babel/core babel/plugin-syntax-dynamic-import @babel/preset-react @babel/plugin-transform-runtime @babel/preset-env @babel/preset-typescript
我这儿使用的是babel.config.js
的配置方式
配置:
module.exports = function (api) {
api.cache(true)
// 从后往前执行
const presets = [
require("@babel/preset-env"), // 编译转换将其转换为2015的代码
require("@babel/preset-react"), // 编译react
require("@babel/preset-typescript") // 编译typescript
]
// 顺序执行
const plugins = [
// require("react-hot-loader/babel"),
// require("transform-react-jsx-source"), // 开发环境使用
require("@babel/plugin-syntax-dynamic-import"),
require("@babel/plugin-transform-runtime")
]
return {
presets,
plugins
}
}
配置eslint
eslint
配置文件可以使用.eslintrc.json
或者.eslintrc.js
或者package.json
文件通过添加eslintConfig
项配置
eslint配置列表项
-
root
设置为true表示当前文件为根目录 -
parser
解析器,因为是typescript项目,所以添加@typescript-eslint/parser
-
parserOptions
解析器配置选项,react
项目将配置
{
'ecmaVersion': 6, // 指定ECMAScript版本
'sourceType': 'module', // ECMAscript 模块
'ecmaFeatures': { //额外的语言特性
'jsx': true
}
}
-
env
配置文件指宝环境
{
"node": true,
"browser": true,// 支持浏览器
"es6": true
}
-
overrides
为特定类型的文件指定处理器 也可以禁用一组文件的某些配置[数组对象列表]
如我这儿禁用掉.tsx文件不校验某些规则
{
"files": ["*.tsx"],
"rules": {
"@typescript-eslint/explicit-function-return-type": 0,
"react/prop-types": 0
}
}
-
extends
使eslint
继承某些已有配置,或者库。我这儿使用airbnb,airbnb
包含了react
的相关规则,所以一般需要安装eslint-plugin-react
和eslint-plugin-jsx-a11y
等以及promise
规则
安装:npm install --save-dev eslint-plugin-import, eslint-plugin-react, eslint-plugin-react-hooks, and eslint-plugin-jsx-a11y eslint-plugin-promise
"extends": [
'airbnb',
"plugin:promise/recommended"
],
-
plugins
借用官网的话插件可以提供处理器。处理器可以从另一种文件中提取 JavaScript 代码,然后让 ESLint 检测 JavaScript 代码。或者处理器可以在预处理中转换 JavaScript 代码
安装npm install --save-dev eslint-plugin-react-hooks
"plugins": [
"react-hooks", // hooks 规则
"promise"
],
-
rules
配置规则官方地址eslint-rules以及插件对应默认规则配置。
webpack配置eslint-loader
只配置了eslint
规则文件并不会生效,还需要配置对应loader
安装:npm install --save-dev eslint-loader
在webpack
配置module
中添加Loader
配置:
{
enforce: 'pre',
test: /\.(ts|tsx|js)?$/,
loader: 'eslint-loader',
exclude: /node_modules/,
options: {
fix: true // 自动修复
}
}
详细配置规则地址:eslint-loader
引入antd
注意tsconfig 编译器需要配置"moduleResolution": "node"
安装:
npm install --save antd
支持按需引入,需要安装babel-plugin-import
npm install --save-dev babel-plugin-import
babel.config.js
新增以下配置
plugins.push([
"import",
{
"libraryName": "antd",
"style": true
}
])
css modules配置
React
项目跟vue
不一样的是,在配置css模块化的时候,vue可以直接配置一个vue-loader
然后在标签里加上scope就可以了,react需要自己配置
css-loader
完成css模块化
安装依赖:npm install --save less-loader css-loader mini-css-extractPlugin
npm install --save less
由于antd不需要对样式做模块化处理所以在配置的时候需要区分(node_modules)下配置:
{
test: /\.(less|css)/,
include: /node_modules/, // 对node_modules加载的css不做模块化解析,antd cssmodules样式无法加载
use: [
MiniCssExtractPlugin.loader,
// 'style-loader',
'css-loader',
'postcss-loader',
{
loader: 'less-loader',
options: {
javascriptEnabled: true
}
}
]
},
{
test: /\.(less|css)$/,
exclude: /node_modules/,
use: [
MiniCssExtractPlugin.loader,
// 'style-loader', // 配置mini-css-extract-plugin之后不应该使用style-loader
{
loader: 'css-loader',
options: {
modules: {
localIdentName: '[name]__[local]__[hash:base64:5]'
}
}
},
// 'css-loader',
'postcss-loader',
{
loader: 'less-loader',
options: {
javascriptEnabled: true
}
}
]
},
typescript 支持引入样式
直接在tsx引入less文件会error TS2307: Cannot find module 'moduleA'
所以需要加入声明文件:
具体为何要写这个文件可以看这个地址 模块解析
在src目录下新建types目录并创建style.d.ts
declare module '*.less' {
const content: any;
export default content;
}
总结
建议做项目可以自己一步一步配置,可以先不使用脚手架,这样的在配置的过程中才会知道webpack做了哪些性能优化,以及按照自己想要优化的地方自己去做一些配置,可能比使用脚手架对webpack的熟悉来得快的多。