一、前言
一般我们创建react项目都是通过create-react-app直接创建的,但是create-react-app创建之后,一些webpack配置并没有暴露出来,我们要是想更改webpack的话,还是比较麻烦的,因此本文主要是利用webpack开始搭建一个react项目。
二、项目初始化
1. 运行命令初始化package.json
yarn init
复制代码
或者
npm init
复制代码
如果想要加上默认配置的话,使用
npm init -y 或者 yarn init -y
复制代码
这两种初始化都可以,主要区别是yarn安装的速度更快一点,使用yarn的时候,会自动生成yarn.lock来锁定版本,而npm5.0以后是通过package-lock.json来锁定版本的,并且yarn 的语义化更好一点。
2. 安装webpack
yarn add webpack webpack-cli -D
复制代码
webpack是打包代码依赖的核心内容,而webpack-cli是一个用来在命令行中运行webpack的工具,webpack从4.0版本开始,就必须要同时安装webpack-cli。
3. 配置入口
入口文件指示webpack应该使用哪个文件来作为构建内部依赖图的开始,可以配置单个入口文件,也可以配置多个入口文件,具体语法详见:入口配置。本文这里只配置单入口。 新建一个src文件夹,里面新建一个文件 index.js,然后新建一个文件 webpack.config.js,里面配置入口文件entry。
4. 配置出口
出口文件即告诉webpack在哪输出它所创建的那些文件,以及如何命名这些输出的文件,默认值为./dist。出口配置里面的filename用于输出文件的文件名,path是输出目录的绝对路径。
5. 区分环境
一般项目都需要区分是开发环境还是线上环境,因此安装cross-env
来区分环境。
yarn add cross-env -D
复制代码
安装好了之后,具体的文件里面可以通过 process.env.NODE_ENV
来判断当前的环境。
6. 配置loader
因为webpack自身只理解js,所以loader是让webpack可以处理那些非js类型的文件,可以将所有类型的文件转化为webpack能够理解的有效模块。loader主要是有两个属性,test属性和use属性,test
属性用于标识出应该被对应的 loader 进行转换的某个或某些文件, use
属性,表示进行转换时,应该使用哪个 loader。
7. 配置plugin
plugin表示的是插件,插件功能非常多,可以用来处理各种各样的任务,主要是为了解决loader无法实现的其他事。
三、项目配置
1. 创建首页页面
webpack打包出来的都只有js文件,使用 html-webpack-plugin
可以自定义一个html模板,最终html文件会被打包到 dist文件夹,并且也会把打包好的js文件引入。
yarn add html-webpack-plugin -D
复制代码
在src下面创建一个index.html,webpack.config.js配置如下:
2. 配置项目启动
可以安装下webpack-dev-server
,这样每次项目更改的时候,浏览器都可以自动刷新。
yarn add webpack-dev-server -D
复制代码
接着配置下webpack.config.js,加下运行的端口 最后在package.json里面设置下启动命令
3. 安装react以及babel相关插件
@babel/core
是babel的核心模块,@babel/preset-env
内预设不同环境的语法转化插件,默认将es6转化为es5。
yarn add react react-dom
yarn add @babel/core
yarn add @babel/preset-env @babel/preset-react babel-loader
复制代码
4. 启动react项目
首先设置一个index.html
然后将index.js改成react语法形式
接着运行 yarn start 即可运行成功
5. 增加样式配置
样式文件需要增加loader,首先安装css-loader
和style-loader
。
yarn add css-loader style-loader -D
复制代码
webpack.config.js 增加对css文件的loader配置,注意style-loader要写在css-loader前面,因为style-loader是将解析后的内容插入到页面,让样式生效,css-loader是解析css,需要先解析再插入,所以css-loader放最右边,先执行。
有时候根据项目的不同,我们可能会写.less或者.scss的样式文件,以.less为例,我们需要增加less的识别配置,首先安装
less
和less-loader
插件。
yarn add less less-loader -D
复制代码
webpack.config.js增加配置如下:
由于这里没有把css 和 html 分开,所以打包的时候,是把样式用style形式嵌入到页面的,我们可以引入单独打包css的plugin,将css样式单独打包,然后通过外部引用进来。
yarn add mini-css-extract-plugin -D
复制代码
webpack.config.js配置如下,需要注意的是MiniCssExtractPlugin取代了原来的style-loader的位置,不需要再使用style-loader了
。
引入mini-css-extract-plugin前:
引入mini-css-extract-plugin后:
给样式配置通用前缀,引入
postcss-loader
和 autoprefixer
yarn add postcss-loader autoprefixer -D
复制代码
webpack.config.js增加配置如下: 最后效果图:
6. 配置字体、图片以及文件
项目里经常会出现字体以及图片,因此需要对字体和图片引入特定的loader来配置,此处安装url-loader
来进行配置,url-loader
对file-loader
有依赖,所以也需要安装下file-loader
。
yarn add url-loader file-loader -D
复制代码
webpack.config.js增加配置如下:(注意:本文的webpack版本为5.0以上,webpack5的url-loader,file-loader已经弃用,webpack5改用的是asset-module,如果想要继续使用的话,需要在use后面加上type: 'javascript/auto',url-loader默认采用ES模块语法,即import '…/aaa.png', 如果在引入css文件时是comandjs语法就会报错require('./css/normal.css'),所以需要将esModule设置为false,本文的图片是新建了一个public文件夹,然后在public文件夹里面还新建了一个images文件夹来放图片,所以include写的是我自己的图片路径,可按照需要改成你自己的图片路径
)
运行yarn run build,打包后的效果如下图所示:
页面如果要通过img来引入图片的话,可以通过require来导入:
<img src={require('./assets/images/cat.png')} />
复制代码
四、项目优化
1. 分环境配置webpack
基于以上两步,我们搭建了一个基本的 webpack+ react的环境,但是上述搭建起来的项目过于简单,针对以上搭建的,我们可以进一步优化,首先将webpack按照环境来分开配置,分成开发环境和线上环境。 首先安装插件,用来合并webpack之间的配置。
yarn add webpack-merge -D
复制代码
根目录下新建文件夹webpack,然后新建三个文件,webpack.config.js webpack.dev.js webpack.prod.js。
- webpack.config.js配置如下
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = {
entry: {
app: "./src/index.js",
},
output: {
path: path.resolve(__dirname, "../dist"),
filename: "[name].bundle.js",
clean: true
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: "babel-loader",
options: {
presets: ["@babel/preset-react"],
},
},
},
{
test: /\.(css|less)$/,
exclude: /node_modules/,
use: [
{ loader: MiniCssExtractPlugin.loader },
"css-loader",
"less-loader",
],
},
{
test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
exclude: /node_modules/,
include: [path.resolve("./public/images")],
use: [
{
loader: 'url-loader',
options: {
limit: 8192,
esModule: false
}
}
],
type: 'javascript/auto'
},
],
},
plugins: [
new HtmlWebpackPlugin({ template: "./src/index.html" }),
new MiniCssExtractPlugin(),
],
devServer: {
port: 8000,
open: true,
},
};
复制代码
- webpack.dev.js 配置如下
const webpack = require("webpack");
const webpackMerge = require("webpack-merge");
const baseConfig = require("./webpack.config");
const config = {
mode: "development",
cache: {
type: "memory", // 使用内存缓存
},
};
const mergedConfig = webpackMerge.merge(baseConfig, config);
module.exports = mergedConfig;
复制代码
- webpack.prod.js 配置如下
const webpack = require("webpack");
const webpackMerge = require("webpack-merge");
const baseConfig = require("./webpack.config");
const config = {
mode: "production",
cache: {
type: "filesystem",
buildDependencies: {
config: [__filename], //使用文件缓存
},
},
optimization: {
minimize: true,
moduleIds: "deterministic",
},
};
const mergedConfig = webpackMerge.merge(baseConfig, config);
module.exports = mergedConfig;
复制代码
- package.json里面的配置更改如下:
"scripts": {
"build": "webpack --config webpack/webpack.dev.js",
"build:prod": "cross-env NODE_ENV=production webpack --config webpack/webpack.prod.js",
"start": "webpack serve --config webpack/webpack.dev.js"
},
复制代码
当前目录如下:
2. 优化src的目录结构
src目录更改如下:
- 新建 assets 文件夹,用来存放静态资源,比如图片和字体文件
- 新建 components 文件夹,用来存放组件
- 新建 pages 文件夹,用来存放页面文件
- 新建 routes 文件夹,用来存放路由
- 新建 api 文件夹,用来存放接口请求文件
- 新建 App.js,设置主页面
- src里面原有的index.html迁移到public.html里面
- webpack.config.js 里面对应的地方修改如下:
3.代码压缩打包
压缩css,引入插件 css-minimizer-webpack-plugin
yarn add css-minimizer-webpack-plugin -D
复制代码
webpack.config.js增加如下配置:
压缩js,webpack5默认会在生产环境压缩js,开发环境不会压缩,当然我们可以通过手动配置来实现一些其他的压缩,webpack5自带了terser-webpack-plugin
插件,但是如果你想要自己配置压缩js的话,还是需要安装terser-webpack-plugin
的。
yarn add terser-webpack-plugin -D
复制代码
webpack.dev.js 增加配置如下:
五、ts环境配置
1.安装ts 和 ts-loader
yarn add typescript ts-loader -D
复制代码
webpack.config.js增加配置如下:
2.增加tsconfig.json
tsconfig.json指定了编译项目所需的根目录下的文件以及编译选项。
{
"compilerOptions": {
"target": "es5",
"lib": ["dom", "es5", "es6", "es7", "dom.iterable", "esnext"],
"allowJs": true,
"skipLibCheck": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"noFallthroughCasesInSwitch": true,
"module": "esnext",
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": false,
"jsx": "react-jsx",
"downlevelIteration": true
},
"include": ["src"]
}
复制代码
3.增加react的类型校验
yarn add @types/react @types/react-dom -D
复制代码
4.修改文件后缀
将原来的index.js 和 App.js 改为 index.tsx App.tsx,改名之后,index.tsx里面需要引入App,这时候会报错,此时可以将 import App from "./App.tsx"的后缀去掉,改为 import App from "./App",接着在webpack.config.js里面增加拓展名。
webpack.config.js增加如下配置,extensions扩展名选项在resolve追踪到的文件如果没有扩展名时,会尝试在其提供的扩展名选项里进行匹配。
5.结果
经过上述配置,最后页面可以成功显示。至此,webpack+react+ts项目搭建成功。