前言

经过前面的初始化,提升开发体验和集成了一堆工具,调整了项目结构等等之后,我们是时候考虑进行项目打包了。 在这篇博客中,我们不考虑开发环境和生产环境的配置分别,我们只看打包需要进行的配置项,所以我们需要做的如下: 0. 添加打包路径工具

  1. 添加打包命令
  2. 进行css和js分离
  3. 修改html-webpack-plugin配置项
  4. 添加react-loadablereact-router,进行代码分离和按需加载
  5. 添加optimization,进行第三方库代码分离
  6. 进行代码压缩
  7. 关于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文件体积巨大,从而拖累页面的加载速度。

  1. webpack 4+版本中,我们可以使用mini-css-extract-plugin进行css代码的分离,所以首先安装它npm install -D mini-css-extract-plugin
  2. 然后我们到build/plugins.js中添加这个插件:
  3. 最后需要注意,之前在提升开发体验这一章中有提到过一点,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(这一步可以进行开发环境和生产环境的区分,在文章中不进行区分):
  4. 经过上面的步骤,我们可以打包进行测试: 运行npm run build可以发现打包结果中css文件已经进行了分离: 而在打包出来的index.html中也可以发现这个css文件被引入了:
  5. 最后我们再在打包路径中将打包出来的js文件用js文件夹包裹起来即可:

修改html-webpack-plugin配置项

这一步主要用于压缩打包出来的index.html文件,但是单页面应用的话html内容其实不多,所以做不做也差不多,在本文章中也只是做个介绍:

  1. 首先在html-webpack-plugin中利用的是html-minifier来做压缩工作的,所以详细配置点击进去看即可,常用的如下:
  2. 第二个需要提一下则是inject这个配置项,该项指定资源如何注入,我们直接使用默认的true即可,他会将js资源注入到<body>标签的底部,如果要注入到头部填写head即可

添加react-loadablereact-router,进行代码分离和按需加载

这一步和下一步都是在进行代码的拆分,考虑的是如果所有文件都塞进一个js文件中,会导致这个js文件体积臃肿,而单页面应用的所有构建又是依赖于这个js文件,所以需要进行代码分离,只加载当前页面需要构建的js文件。 通常来说,我们会根据react-router分的页面来进行代码分离,再用react-loadable进行分割出来的代码的异步加载(当然你也可以将所有组件都进行代码分离然后异步加载)。 所以在这里我们先利用react-router分两个页面homepage出来:

  1. 首先我们安装react-router: npm install -S react-router-dom,然后在src/containers/views中新建HomePage组件:
  2. 接着安装react-loadable: npm install -S react-loadable, 然后在src/containers/shared中新建App组件: 之后在里面的index.tsx中引用react-routerreact-loadable进行组件按需加载: 当然不要忘了使用react-hot-loader: 这一步需要注意的是,Loadable这个函数中的loading参数是必须有的,至于如何使用可以自行参考react-loadable的github链接。
  3. 这个时候去到页面看一下: 在/路径下,没有加载page.js这个文件,而切换到/page路径则会加载page.js文件,这个时候按需加载就完成了:
  4. 最后我们观察一下打包后的js文件可以发现已经进行了分离:

会用optimization进行第三方库代码分离

optimization是webpack4+版本中新出的配置项,这个配置项的功能主要是进行代码压缩,优化。 在本节中,我们需要将用到的处于node_modules中的第三方代码进行分离,在这里主要用到的是两个配置项optimization.runtimeChunkoptimization.splitChunks,其中runtimeChunk用于生成维系各各代码块关系的代码,splitChunks则用于指定需要进行分块的代码,和分块后文件名。

  1. 我们去到build目录下,新建optimization.js,并添加如下代码: 然后在webpack.config.js中引入这个配置:
  2. 最后我们打包试试看可以发现第三方代码都被打包进vendor.js文件中了: 你可以通过比对在添加optimization之前和之后打包出来的app.js文件来看出效果。

进行代码压缩

在这一步中,我们主要是做js和css的代码压缩和优化

  1. 在上面阶段中,我们打包出来的js代码是已经经过压缩的: 所以在这个阶段我们可以利用uglifyjs-webpack-plugin进行一些压缩优化: 首先我们需要安装npm install -D uglifyjs-webpack-plugin,然后去到build/optimization.js中添加如下代码即可,具体的优化见代码: PS: 这里有一个点需要注意,在uglifyjs-webpack-plugin这个插件中,如果是2.x版本的话是不支持es6规范的,所以建议安装1.x版本,而我这里的版本是:
  2. 然后我们进行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配置项用于在构建过程中忽略一些常用包的集成,从而降低构建时间和打包后的包大小,它的配置也很简单,在本章中只做简单介绍: 在本项目中,我们可以将reactreact-dom添加进externals中,然后在html模板中引入它们的外部链接:

  1. 我们先去到webpack.config.js中,添加externals选项,并且把reactreact-dom添加进去: 这个配置项接收的是一个对象(其他形式请自行查阅webpack文档),对象的键是指webapck在获取这个模块时候require时候的参数,而对应的值则是标明你打算将这个模块挂载的变量名,这里是挂载在window对象中的。
  2. 去到build/tpl/index.html中,引入cdn中reactreact-dom的链接:
  3. 重启项目,可以发现在npm run dev中能够正常使用,并且也已经引入了两者的外部资源:
  4. 最后我们来对比一下打包后模块占用情况: 再来对比一下两者打包出来的包体积大小: