webpack:从入门到真实项目配置

Posted 前端大学

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了webpack:从入门到真实项目配置相关的知识,希望对你有一定的参考价值。

新媒体管家

前端大学,每天精选前端干货文章,帮您提升前端技术!


该文使用的 Webpack 版本为 3.6.0,本文分两部分。第一步是简单的使用 webpack,第二部分通过一个真实项目来配置 webpack,没有使用任何的 CLI,都是一步步配置直到完成生产代码的打包。这是本项目对应的仓库,每个小节基本都对应了一次 commit。

这是本文的大纲,如果觉得有兴趣你就可以往下看了




Webpack 到底是什么

自从出现模块化以后,大家可以将原本一坨代码分离到个个模块中,但是由此引发了一个问题。每个 JS 文件都需要从服务器去拿,由此会导致加载速度变慢。Webpack 最主要的目的就是为了解决这个问题,将所有小文件打包成一个或多个大文件,官网的图片很好的诠释了这个事情,除此之外,Webpack 也是一个能让你使用各种前端新技术的工具。

webpack:从入门到真实项目配置

简单使用

安装

在命令行中依次输入

webpack:从入门到真实项目配置

然后按照下图创建文件

webpack:从入门到真实项目配置

在以下文件写入代码

webpack:从入门到真实项目配置

现在我们开始配置最简单的 webpack,首先创建 webpack.config.js 文件,然后写入如下代码

webpack:从入门到真实项目配置

现在我们可以开始使用 webpack 了,在命令行中输入

node_modules/.bin/webpack

没问题的话你应该可以看到类似的样子

webpack:从入门到真实项目配置

可以发现原本两个 JS 文件只有 100B,但是打包后却增长到 2.66KB,这之中 webpack 肯定做了什么事情,我们去 bundle.js 文件中看看。

把代码简化以后,核心思路是这样的

webpack:从入门到真实项目配置

因为 module.export 浏览器是不支持的,所以 webpack 将代码改成浏览器能识别的样子。现在将 index.html 文件在浏览器中打开,应该也可以看到正确的 log。

我们之前是在文件夹中安装的 webpack,每次要输入 node_modules/.bin/webpack 过于繁琐,可以在 package.json 如下修改

"scripts": {    "start": "webpack"  },

然后再次执行 npm run start,可以发现和之前的效果是相同的。简单的使用到此为止,接下来我们来探索 webpack 更多的功能。

Loader

Loader 是 webpack 一个很强大功能,这个功能可以让你使用很多新的技术。

Babel

Babel 可以让你使用 ES2015/16/17 写代码而不用顾忌浏览器的问题,Babel 可以帮你转换代码。首先安装必要的几个 Babel 库

npm i --save-dev babel-loader babel-core babel-preset-env

先介绍下我们安装的三个库

  • babel-loader 用于让 webpack 知道如何运行 babel

  • babel-core 可以看做编译器,这个库知道如何解析代码

  • babel-preset-env 这个库可以根据环境的不同转换代码

接下来更改 webpack-config.js 中的代码

webpack:从入门到真实项目配置

配置 Babel 有很多方式,这里推荐使用 .babelrc 文件管理。

webpack:从入门到真实项目配置

现在将之前 JS 的代码改成 ES6 的写法

webpack:从入门到真实项目配置

执行 npm run start,再观察 bundle.js 中的代码,可以发现代码被转换过了,并且同样可以正常 输出3。

当然 Babel 远不止这些功能,有兴趣的可以前往官网自己探索。

处理图片

这一小节我们将使用 url-loader 和 file-loader,这两个库不仅可以处理图片,还有其他的功能,有兴趣的可以自行学习。

先安装库

npm i --save-dev url-loader file-loader

创建一个 images 文件夹,放入两张图片,并且在 app 文件夹下创建一个 js 文件处理图片
,目前的文件夹结构如图

webpack:从入门到真实项目配置

webpack:从入门到真实项目配置

接下来修改 webpack.config.js 代码

webpack:从入门到真实项目配置

运行 npm run start,打包成功如下图

webpack:从入门到真实项目配置


可以发现大的图片被单独提取了出来,小的图片打包进了 bundle.js 中。

在浏览器中打开 HTML 文件,发现小图确实显示出来了,但是却没有看到大图,打开开发者工具栏,可以发现我们大图的图片路径是有问题的,所以我们又要修改 webpack.config.js 代码了。

webpack:从入门到真实项目配置

最后运行下 npm run start,编译成功了,再次刷新下页面,可以发现这次大图被正确的显示了。下一小节我们将介绍如何处理 CSS 文件。

处理 CSS 文件

添加 styles 文件夹,新增 addImage.css 文件,然后在该文件中新增代码

img {    border: 5px black solid; }.test {border: 5px black solid;}

这一小节我们先使用 css-loader 和 style-loader 库。前者可以让 CSS 文件也支持 impost,并且会解析 CSS 文件,后者可以将解析出来的 CSS 通过标签的形式插入到 HTML 中,所以后面依赖前者。

npm i --save-dev css-loader style-loader

首先修改 addImage.js 文件

webpack:从入门到真实项目配置

然后修改 webpack.config.js 代码

webpack:从入门到真实项目配置

运行下 npm run start,然后刷新页面,可以发现图片被正确的加上了边框,现在我们来看一下 HTML 的文件结构

webpack:从入门到真实项目配置

从上图可以看到,我们在 addImage.css 文件中写的代码被加入到了 style 标签中,并且因为我们开启了 CSS 模块化的选项,所以 .test 被转成了唯一的哈希值,这样就解决了 CSS 的变量名重复问题。

但是将 CSS 代码整合进 JS 文件也是有弊端的,大量的 CSS 代码会造成 JS 文件的大小变大,操作 DOM 也会造成性能上的问题,所以接下来我们将使用 extract-text-webpack-plugin插件将 CSS 文件打包为一个单独文件

首先安装 npm i --save-dev extract-text-webpack-plugin

然后修改 webpack.config.js 代码

webpack:从入门到真实项目配置

运行下 npm run start,可以发现 CSS 文件被单独打包出来了

webpack:从入门到真实项目配置

但是这时候刷新页面会发现图片的边框消失了,那是因为我们的 HTML 文件没有引用新的 CSS 文件,所以这里需要我们手动引入下,在下面的章节我们会通过插件的方式自动引入新的文件。

请依次按照以下代码操作

git clone https://github.com/KieSun/webpack-demo.gitcd webpack-demo // 切换到 0.1 标签上并创建一个新分支 git checkout -b demo 0.1 // 查看分支是否为 demo,没问题的话就可以进行下一步 gst

如何在项目中使用 webpack

项目中已经配置了很简单的 babel 和 webpack,直接运行 npm run start 即可

webpack:从入门到真实项目配置

这时候你会发现这个 bundle.js 居然有这么大,这肯定是不能接受的,所以接下来章节的主要目的就是将单个文件拆分为多个文件,优化项目。

分离代码

先让我们考虑下缓存机制。对于代码中依赖的库很少会去主动升级版本,但是我们自己的代码却每时每刻都在变更,所以我们可以考虑将依赖的库和自己的代码分割开来,这样用户在下一次使用应用时就可以尽量避免重复下载没有变更的代码,那么既然要将依赖代码提取出来,我们需要变更下入口和出口的部分代码。

webpack:从入门到真实项目配置

现在我们 build 一下,看看是否有惊喜出现

webpack:从入门到真实项目配置
webpack:从入门到真实项目配置

真的有惊喜。。为什么 bundle 文件大小压根没变。这是因为 bundle 中也引入了依赖库的代码,刚才的步骤并没有抽取 bundle 中引入的代码,接下来让我们学习如何将共同的代码抽取出来。

抽取共同代码

在这小节我们使用 webpack 自带的插件 CommonsChunkPlugin

webpack:从入门到真实项目配置


当我们重新 build 以后,会发现 bundle 文件很明显的减小了体积

webpack:从入门到真实项目配置

但是我们使用哈希来保证缓存的同时会发现每次 build 都会生成不一样的文件,这时候我们引入另一个插件来帮助我们删除不需要的文件。

npm install --save-dev clean-webpack-plugin

然后修改配置文件

webpack:从入门到真实项目配置

然后 build 的时候会发现以上文件被删除了。

因为我们现在将文件已经打包成三个 JS 了,以后也许会更多,每次新增 JS 文件我们都需要手动在 HTML 中新增标签,现在我们可以通过一个插件来自动完成这个功能。

npm install html-webpack-plugin --save-dev

然后修改配置文件

webpack:从入门到真实项目配置

执行 build 操作会发现同时生成了 HTML 文件,并且已经自动引入了 JS 文件

webpack:从入门到真实项目配置

按需加载代码

在这一小节我们将学习如何按需加载代码,在这之前的 vendor 入口我发现忘记加入 router 这个库了,大家可以加入这个库并且重新 build 下,会发现 bundle 只有不到 300KB 了。

现在我们的 bundle 文件包含了我们全部的自己代码。但是当用户访问我们的首页时,其实我们根本无需让用户加载除了首页以外的代码,这个优化我们可以通过路由的异步加载来完成。

现在修改 src/router.js

webpack:从入门到真实项目配置

然后执行 build 命令,可以发现我们的 bundle 文件又瘦身了,并且新增了几个文件

webpack:从入门到真实项目配置

将 HTML 文件在浏览器中打开,当点击路由跳转时,可以在开发者工具中的 Network 一栏中看到加载了一个 JS 文件。

首页

webpack:从入门到真实项目配置

点击右上角 Random Artist 以后

webpack:从入门到真实项目配置

自动刷新

每次更新代码都需要执行依次 build,并且还要等上一会很麻烦,这一小节介绍如何使用自动刷新的功能。

首先安装插件

npm i --save-dev webpack-dev-server

然后修改 packet.json 文件

webpack:从入门到真实项目配置

现在直接执行 npm run dev 可以发现浏览器自动打开了一个空的页面,并且在命令行中也多了新的输出

webpack:从入门到真实项目配置

等待编译完成以后,修改 JS 或者 CSS 文件,可以发现 webpack 自动帮我们完成了编译,并且只更新了需要更新的代码

webpack:从入门到真实项目配置

但是每次重新刷新页面对于 debug 来说很不友好,这时候就需要用到模块热替换了。但是因为项目中使用了 React,并且 Vue 或者其他框架都有自己的一套 hot-loader,所以这里就略过了,有兴趣的可以自己学习下。

生成生产环境代码

现在我们可以将之前所学和一些新加的插件整合在一起,build 生产环境代码。

npm i --save-dev url-loader optimize-css-assets-webpack-plugin file-loader extract-text-webpack-plugin

修改 webpack 配置

webpack:从入门到真实项目配置

webpack:从入门到真实项目配置

webpack:从入门到真实项目配置

修改 packet.json 文件

webpack:从入门到真实项目配置

执行 npm run build


webpack:从入门到真实项目配置


可以看到我们在经历了这么多步以后,将 bundle 缩小到了只有 27.1KB,像 vendor 这种常用的库我们一般可以使用 CDN 的方式外链进来。

补充

webpack 配置上有些实用的小点在上文没有提到,统一在这里提一下。

后记

如果你是跟着本文一个个步骤敲下来的,那么大部分的 webpack 配置你应该都是可以看懂了,并且自己应该也知道如何去配置。谢谢大家看到这里,这是本项目对应的仓库,每个小节基本都对应了一次 commit。

文章较长,有错误也难免,如果你发现了任何问题或者我有任何表述的不明白的地方,都可以留言给我。

原文链接:https://juejin.im/post/59bb37fa6fb9a00a554f89d2?utm_source=gold_browser_extension


 推荐阅读:

1.

2.

3.

感谢.转发.分享一起提升技术


以上是关于webpack:从入门到真实项目配置的主要内容,如果未能解决你的问题,请参考以下文章

webpack 从入门到放弃

webpack从入门到精通

webpack入门笔记

webpack 入门基础配置

React从入门到放弃之前奏:webpack4简介

Webpack入门指南: 入口,输出,加载器和插件