相关文章和阅读顺序
搭建Typescript+React项目模板(1) --- 项目初始化
搭建 Typescript+React 项目模板 (2) --- 提升开发体验
搭建 Typescript+React 项目模板 (3) --- 整理项目和杂项
搭建 Typescript+React 项目模板 (4) --- 项目打包
搭建 Typescript+React 项目模板 (5) --- 团队规范
文章已同步更新到掘金专栏(https://juejin.im/user/5a77c815f265da4e9518bebc/posts)
项目地址
前言
经过前面的初始化,提升开发体验和集成了一堆工具,调整了项目结构等等之后,我们是时候考虑进行项目打包了。
在这篇博客中,我们不考虑开发环境和生产环境的配置分别,我们只看打包需要进行的配置项,所以我们需要做的如下:
- 添加打包路径工具
- 添加打包命令
- 进行css和js分离
- 修改
html-webpack-plugin
配置项 - 添加
react-loadable
和react-router
,进行代码分离和按需加载 - 添加optimization,进行第三方库代码分离
- 进行代码压缩
- 关于
externals
添加打包命令
我们先去webpack.config.js
中观察一下output
这个配置项:
该配置项指定了打包路径和打包后的js文件名,在
webpack
的配置项中,output
是必须有的。接着我们去到
package.json
中在script
中添加打包命令build
,该命令引用我们的webpack.config.js
配置文件:之后试试运行
npm run build
,会发现已经将项目打包出来了:添加打包路径工具
在上一步中,我们已经知道打包出来的文件位于根目录下的dist
文件夹中,所以这个路径工具的添加指向dist
文件夹:
我们去到build/utils.js
文件中,添加如下代码:
以后指定打包文件存放路径的时候就可以直接使用这个工具进行指定。
分离css文件
在上面打包的结果中,我们会发现只有一个app.js
文件,而实际上我们是有写css样式的,但是现在的却并没有这个css文件,这是因为webpack
将所有的资源(包含js
, css
等等)都看成是chunk
,然后一起打包进一个文件中,这样会导致打包出来的js文件体积巨大,从而拖累页面的加载速度。
- 在
webpack 4+
版本中,我们可以使用mini-css-extract-plugin
进行css代码的分离,所以首先安装它npm install -D mini-css-extract-plugin
。 - 然后我们到
build/plugins.js
中添加这个插件:
- 最后需要注意,之前在提升开发体验这一章中有提到过一点,
style-loader
用于将css-loader
编译出来的代码转为js代码并写入js文件中,所以在这里,我们需要用mini-css-extract-plugin
中的loader去替换掉style-loader
,让它写入单独的css文件而不是js文件中:
我们去到build/rules/styleRules.js
中,将原本的style-loader
全都替换成mini-css-extract-plugin
的loader(这一步可以进行开发环境和生产环境的区分,在文章中不进行区分):
- 经过上面的步骤,我们可以打包进行测试:
运行npm run build
可以发现打包结果中css文件已经进行了分离:
而在打包出来的index.html
中也可以发现这个css文件被引入了:
-
最后我们再在打包路径中将打包出来的js文件用js文件夹包裹起来即可:
修改html-webpack-plugin
配置项
这一步主要用于压缩打包出来的index.html
文件,但是单页面应用的话html
内容其实不多,所以做不做也差不多,在本文章中也只是做个介绍:
- 首先在
html-webpack-plugin
中利用的是html-minifier来做压缩工作的,所以详细配置点击进去看即可,常用的如下:
- 第二个需要提一下则是
inject
这个配置项,该项指定资源如何注入,我们直接使用默认的true
即可,他会将js资源注入到<body>
标签的底部,如果要注入到头部填写head
即可
添加react-loadable
和react-router
,进行代码分离和按需加载
这一步和下一步都是在进行代码的拆分,考虑的是如果所有文件都塞进一个js文件中,会导致这个js文件体积臃肿,而单页面应用的所有构建又是依赖于这个js文件,所以需要进行代码分离,只加载当前页面需要构建的js文件。
通常来说,我们会根据react-router
分的页面来进行代码分离,再用react-loadable进行分割出来的代码的异步加载(当然你也可以将所有组件都进行代码分离然后异步加载)。
所以在这里我们先利用react-router
分两个页面home
和page
出来:
- 首先我们安装
react-router
:
npm install -S react-router-dom
,然后在src/containers/views
中新建Home
和Page
组件:
- 接着安装
react-loadable
:
npm install -S react-loadable
, 然后在src/containers/shared
中新建App
组件:
之后在里面的index.tsx
中引用react-router
和react-loadable
进行组件按需加载:
当然不要忘了使用react-hot-loader
:
这一步需要注意的是,Loadable
这个函数中的loading参数是必须有的,至于如何使用可以自行参考react-loadable
的github链接。 - 这个时候去到页面看一下:
在/
路径下,没有加载page.js
这个文件,而切换到/page
路径则会加载page.js
文件,这个时候按需加载就完成了:
-
最后我们观察一下打包后的js文件可以发现已经进行了分离:
会用optimization
进行第三方库代码分离
optimization
是webpack4+版本中新出的配置项,这个配置项的功能主要是进行代码压缩,优化。
在本节中,我们需要将用到的处于node_modules
中的第三方代码进行分离,在这里主要用到的是两个配置项optimization.runtimeChunk
和optimization.splitChunks
,其中runtimeChunk
用于生成维系各各代码块关系的代码,splitChunks
则用于指定需要进行分块的代码,和分块后文件名。
- 我们去到
build
目录下,新建optimization.js
,并添加如下代码:
然后在webpack.config.js
中引入这个配置:
- 最后我们打包试试看可以发现第三方代码都被打包进
vendor.js
文件中了:
你可以通过比对在添加optimization
之前和之后打包出来的app.js
文件来看出效果。
进行代码压缩
在这一步中,我们主要是做js和css的代码压缩和优化
- 在上面阶段中,我们打包出来的js代码是已经经过压缩的:
所以在这个阶段我们可以利用uglifyjs-webpack-plugin进行一些压缩优化:
首先我们需要安装npm install -D uglifyjs-webpack-plugin
,然后去到build/optimization.js
中添加如下代码即可,具体的优化见代码:
PS: 这里有一个点需要注意,在uglifyjs-webpack-plugin
这个插件中,如果是2.x版本的话是不支持es6规范的,所以建议安装1.x版本,而我这里的版本是:
- 然后我们进行css代码的压缩,这里需要使用到optimize-css-assets-webpack-plugin插件:
npm install -D optimize-css-assets-webpack-plugin
。
我们先去Home
组件中随意添加一个样式并使用它:
然后再去到build/optimization.js
添加如下代码:
具体的插件使用方式可以自行上github查看该插件。
最后查看打包出来后的css代码:
到现在压缩代码步骤也做完了,最后将介绍一下webpack.externals
这个选项。
关于externals
webpack.externals配置项用于在构建过程中忽略一些常用包的集成,从而降低构建时间和打包后的包大小,它的配置也很简单,在本章中只做简单介绍:
在本项目中,我们可以将react
和react-dom
添加进externals
中,然后在html模板中引入它们的外部链接:
- 我们先去到
webpack.config.js
中,添加externals
选项,并且把react
和react-dom
添加进去:
这个配置项接收的是一个对象(其他形式请自行查阅webpack文档),对象的键是指webapck在获取这个模块时候require
时候的参数,而对应的值则是标明你打算将这个模块挂载的变量名,这里是挂载在window对象中的。 - 去到
build/tpl/index.html
中,引入cdn中react
和react-dom
的链接:
- 重启项目,可以发现在
npm run dev
中能够正常使用,并且也已经引入了两者的外部资源:
-
最后我们来对比一下打包后模块占用情况:
再来对比一下两者打包出来的包体积大小: