尝试配置webpack来编译项目
尝试配置webpack来编译项目
主要是之前的两个项目,后台管理那个用的react-cli
,官网那个用的vue-cli
,基本不用写到和webpack
有关的配置。
(官网那个写了点,不过是在vue.config.js
文件内进行编写的,文件内其实也有属性可以直接编写原生的webpack
配置)。
本文主要简单写写webpack
的一些常用的配置…,当然,这也是我第一次直接使用webpack
来编译项目。
正文
可以选择直接在官网学习,英语 ok 的直接英文文档,像我这种英语半吊子的,两者结合着看,不懂翻一下,顺便学下英语…
不过还是强烈建议英文文档,中文文档有些地方更新不及时好像…
webpack
可以理解为一个打包器,可以把分散在不同位置的资源(js
,css
,jpg
,ts
等等)bundle
成一个输出的文件,首页的图很好地表明了webpack
的作用。
即使是顶破天的技术,归根结底基本是要编译成js
,html
,css
以及其他的静态资源(static assets
),因为浏览器就只认这个欸…
目前 webpack 的版本在 5(2020 年 10 月 10 号发布的),下面的链接为关于新版webpack
的一些描述。
似乎写的有点偏,ok,不多 bb,直接上代码就完事。
首先,需要建一个node
的项目,使用yarn init
来创建(其实就是初始化个package.json
文件)。
创建完差不多是下面这样的(index.js
文件是我自己添加的,现在是一个空的文件)。
现在我们全局装下webpack
,使用yarn global add webpack
就可以安装最新版的webpack
了。
可以用webpack -v
看下版本,如果第一次装的话,webpack
还会提示你安装webpack-cli
,按照提示安装就可以了。
接下来就正式开始编写代码了。
我们现在index.js
写个简单的console.log
输出。
接下来编写webpack
的核心配置代码webpack.config.js
。
在编写配置代码之前,我们需要简单的理解 webpack 中的两个配置属性。
entry
An entry point indicates which module
webpack
should use to begin building out its internal dependency graph.webpack
will figure out which other modules and libraries that entry point depends on (directly and indirectly).
By default its value is./src/index.js
, but you can specify a different (or multiple entry points) by setting an entry property in the webpack configuration. —— entry - webpack
一个入口节点表明webpack
应该以哪个模块来开始建立它内部的依赖网,webpack
会弄清楚入口节点依赖了哪些库或者模块(直接依赖或者间接依赖)
默认情况下的值为./src/index.js
(也就是当前文件夹下的src
目录下的index.js
文件),但你也可以在webpack
配置中通过设置 entry 属性来指定一个不同的(或者多个)入口点。
简单点讲就是指定入口的文件,webpack
就从这个文件开始,把这个文件依赖的其他文件打包进来,而其他文件可能又依赖了其他的文件,那么就会递归这个过程。
output
The output property tells
webpack
where to emit the bundles it creates and how to name these files. It defaults to./dist/main.js
for the main output file and to the./dist
folder for any other generated file. —— output - webpack
output 属性告诉webpack
在哪输出它创建的打包文件以及如何对这些文件命名。默认值为./dist/main.js
为主要的输出文件,./dist
文件夹存放其他任何生成的文件。
结合上面这两个,可以写出一个简单的webpack.config.js
文件。
1 | const path = require("path"); |
然后我们可以在package.json
的script
下新增一条命令。
1 | { |
然后通过yarn build
来执行这条命令。
可以发现打包成功了,没有出现什么错误,并且多了一个dist
文件夹,里面有一个bundle.js
。
生成的bundle.js
内容如下:
1 | console.log("Hello World!"); |
webpack
在默认情况下是production
(生产)模式,这个模式是由配置中的mode
指定的。
可以查看该页面 mode - webpack。
可以修改配置文件为。
1 | const path = require("path"); |
输出如下
1 | /* |
可以发现eval
中出现了"console.log("Hello World!");
这句代码,这句代码对应了我们index.js
的内容。
在顶部的多行注释中,提到了The "eval" devtool has been used (maybe by default in mode: "development").
,也就是在开发环境下会使用eval
这个开发工具。
在开发环境下webpack
会默认启动一些配置,如下(这个表格可以在上面mode
的网址里面找到,对应也有生产mode
下默认的配置)。
1 | // webpack.development.config.js |
回到生产环境下的打包,可以发现生成的文件非常的简单,简答地让人怀疑是不是没打包…,为了看出打包的效果,可以稍稍写多点代码。
1 | console.log("Hello World!"); |
打包之后如下
1 | console.log("Hello World!"), |
可以发现缩进和没必要的空格全部没有了,并且也优化了变量,像el
就被省略了,由于变量a
和b
都没被使用,输出直接生成了一个静态的语句console.log(3)
,省略了这两个变量。
除了js
文件,webpack
也支持导入其他的文件。
1 | // 导入样式 |
当然这样子直接编译是会报错的。
可以看到错误信息中有一句Module parse failed
,也就是模块解析错误。
下一句是You may need an appropriate loader to handler this file type ...
,也就是提示我们需要一个适合的loader
来处理这个文件。
那么就要了解webpack
中的loader
了。
loader
webpack
enables use of loaders to preprocess files. This allows you to bundle any static resource way beyond JavaScript.
webpack
使用各种 loader 来预处理文件,这允许你在JavaScript
上打包任何静态的资源。
所以我们需要一个 loader 来处理css
文件,使得css
文件转成 js 能够理解的代码。
这个 loader 就是css-loader
。
先通过yarn add css-loader -D
来安装css-loader
开发依赖,-D
安装在开发依赖里面。
修改webpack
的配置文件。
1 | const path = require("path"); |
然后我们输出style
这个变量看看是什么样子。
1 | import style from "./css/style.css"; |
我们在dist
目录下创建一个html
文件来引用这个js
文件,然后看看控制台的输出。
可以看到导出了一个数组,也可以理解为css
文件转换成了下面的js
文件。
1 | const o = [["./css/style.css", ".text {↵ font-size: 18px;↵}", ""]]; |
在使用 Vue 的时候,可能会发现开发环境下每个组件的样式会通过style
标签来插入到DOM
中,这就使用到了另一个loader
- style-loader
。
可以安装这个loader
,运行yarn add style-loader -D
。
然后修改配置文件如下:
1 | const path = require("path"); |
然后我们运行打包,打开网页会发现在head
中插入了对应的样式,并且style
变量为一个空的对象。
这里可能有疑问的就是loader
的执行顺序问题。
官方在Loader - Using Loader - Configuration一节的文档中明确指出,loader
是从右往左进行执行的。
Loaders are evaluated/executed from right to left (or from bottom to top).
在Loader Features一节指出了loader
的特性。
每个loader
也有自己的配置,在use
中,我们可以以一个对象来表示一个loader
。
1 | const path = require("path"); |
像style-loader
,除了通过style
标签注入之外,也有其他的一些注入方式。
style-loader
的仓库地址webpack-contrib/style-loader
在README
中,也为我们写明了这些配置。
其中injectType
为配置注入的方式。
可以通过每个loader
对象的options
来配置,这里使用了singletonStyleTag
,也就是只插入一个单独的style
标签。
1 | const path = require("path"); |
然后写另一个 css 文件
1 | import style from "./css/style.css"; |
然后打包,打开浏览器,发现head
中只有一个style
标签了。
如果不加情况下(默认为styleTag
),那么会是两个style
标签,如下:
到现在为止看起来很不错,webpack 发挥了他的功能,也就是打包。
不过还有一点不够智能,我们希望html
文件也可以自动的生成,那就非常完美了,我们只需在开启一个本地的服务器来绑定dist
这个目录,然后每一次打包之后就可以直接打开浏览器就可以看到结果。
这就需要用到webpack
的另一个配置plugin
(插件)了
plugin
While loaders are used to transform certain types of modules, plugins can be leveraged to perform a wider range of tasks like bundle optimization, asset management and injection of environment variables.
loader 用于转化某些模块的类型,而 plugin 被用来执行一些更广泛的任务,比如打包优化,资源管理以及环境变量的注入。
可以简单理解为plugin
的功能更加的强大,可以完成一些做不到的事情,而loader
主要的功能就是转换文件类型。
像为了可以自动生成一个HTML
文件,可以使用HtmlWebpackPlugin
。
插件也要安装对应的npm
包,执行yarn add html-webpack-plugin -D
来安装插件。
然后修改配置文件,新增plugins
属性。
1 | const path = require("path"); |
不过这样子编译的话会出现错误,原因应该是插件需要用到项目的webpack
,而不能使用全局的webpack
。
这里解决办法可以装个项目的webpack
依赖,yarn add webpack -D
。
或者链接下全局的webpack
,yarn link webpack -D
。
这里我使用的是后面的方法。
注意,在执行yarn link webpack -D
,需要在webpack
的包下面执行yarn link
来注册webpack
。
接着我们删除dist
文件夹,然后打包。
发现打包成功了,而且也自动生成了HTML
文件,并且引用了生成的bundle.js
。