前端的小伙伴们对webpack太熟悉不过了,今天这篇文章作为webpack深入浅出系列的第一篇,就直奔主题,记录一下一个项目搭建起来的过程吧。
最简单的webpack例子
我们通常说webpack是一个JavaScript打包工具,那非JavaScript是如何进行打包的呢,在我这一系列的文章中会慢慢解答。但是百里之行始于足下,我们需要先看看webpack是如何做好自己的本职工作的。
webpack config
webpack可以免配置打包,但是一般情况下,我们会提供一个配置文件。在这个简单的例子中我会提供这么一个简单的文件供大家参考:
const path = require('path');
module.exports = {
mode: 'production',
entry: './src/index.js',
output: {
path: path.resolve(__dirname,'dist'),
filename: 'bundle.js'
}
}
这份配置里面的几个关键点其实大家都挺清楚,mode是指定打包环境的,production
在webpack官方文档中描述是:会将DefinePlugin中的process.env.NODE_END的值设置为'production'。为模块和chunk启用确定性混淆名称,FlagDependencyUsagePlugin,FlagIncludeChunksPlugin,ModuleConcatenationPlugin,NoEmitOnErrorsPlugin和Terserplugin。
entry和output分别是入口和出口。
项目文件目录
现在这个示例项目的文件项目目录是这样的:
my-package
- node_modules
- package.json
- yarn.lock
我们把刚才那个配置添加进去,在根目录下创建'webpack.config.js',将刚才的代码复制进去。
创建打包资源
此时在项目下创建src目录,并在目录下创建两个文件:
helloWorld.js
和index.js
// helloWorld
export default {
webpack: 'is good'
}
// index.js
import helloworld from 'helloWorld.js'
console.log(helloworld.webpack)
在命令行输入:npx webpack
或者./node_module/.bin/webpack
命令。
在目录下会生成dist
文件夹,将里面的bundle.js
(我们会在下一篇文章分析这个文件)复制到任意页面中,打开页面在控制台就会得到想要的结果。
总结
这是最简单的一个打包示例,我们可以初步体验下webpack创建打包的步骤。在接下来的文章中,我们在看下如何将页面常见的资源打包进项目中。
其他资源
ES6的解析
其实webpack本身功能特别有限,但是官方以及社区为webpack开发出了很多插件。如果多说两句,实际上webpack和gulp之间只是流程上的区别而已,有想法的朋友其实可以用gulp作出一款类似webpack的工具。
言归正传,对高级语法的解析都是通过babel-loader
实现的。www.babeljs.cn/ 是babel的官网,我也会出一期文章专门整理一下babel的入门(貌似给自己挖了一个坑)。
在webpack中使用babel需要经过以下几步:
- 创建babelrc文件(可以是json文件也可以是js文件);
// .babelrc.js
module.exports = {
"presets":[
"@babel/preset-env"
"@babel/preset-react"
]
}
- 在webpack配置中设置babel-loader的相关配置;
// webpack-config
{
// 注释无关代码
module: {
rules: [
{
test: /.js$/,
use: "babel-loader"
}
]
}
}
这样,再次打包的时候,babel就会将代码编译成浏览器能运行的语法形式了。
CSS解析
解析css需要至少两个loader才能完成,分别是:
- css-loader 用于加载.css文件,转换成commonjs对象;
- style-loader 将样式通过style标签插入到head中; 为了能够使用css预处理器,我们可能还会安装相对应的插件,比如less;
yarn add css-loader style-loader less less-loader -D
然后配置文件里写好对应的配置。
{
test: /.css$/,
use: [
'style-loader',
'css-loader'
]
},
{
test: /.less$/,
use:[
'style-loader',
'css-loader',
'less-loader'
]
}
图片和文字
处理图片和文字的loader是url-loader,和file-loader一样,它能够解析图片和字体资源,不同的是,他可以指定资源的一个大小,如果资源实际大小小于这个值就会被处理成为一个base类型的资源。由于url-loader内部还是依赖了file-loader,需要一同安装。
{
test: /.(jpg|png|gif|jpeg)$/,
use: {
loader: 'url-loader',
options: {
limit: 1024
}
}
}
HTML相关
当js,css,图片等必须的资源都处理结束之后,就要将他们想办法和html建立联系,这样我们就能在打包完成之后直接扔到服务器上进行访问了。
HtmlWebpackPlugin,这是一个plugin,用来将html模版输出到打包好的文件夹下,与其他资源一起进行发布。
plugin在webpack中很重要,他可以设定在不同的打包过程中进行一些操作,不仅限于输入和输出,也不仅限于处理文件。总之很强大,在HtmlWebpackPlugin中,可以进行代码的压缩处理。
{
plugins:[
new HtmlWebpackPlugin({
template: '项目入口html的文件',
filename: '自定义项目html名称',
minify: '压缩相关'
})
]
}
基础部分总结
通过上述配置,一个基本的脚手架就搭建完成了,满足了最基本的开发需求,但是,随着项目越来越大,这个配置的弊端就会暴露出来。 接下来我们看一下如何进阶一些使用。
进阶用法
之前的配置中,我们每次构建之后构建目录都是追加的内容。这样我们的构建目录就会越来越庞大,不仅占用很多资源,也影响着我们的维护。
px2rem
我们在开发移动设备的时候,通常会遇到一个常见的问题:由于手机分辨率的不同,我们写的同一套css字体,元素宽高等样式会出现一些兼容性的问题,典型的就是在一些设备上正常显示,在另一些设备上就会出现过大或者过小。为了解决这个问题,我们可以对我们的css样式进行一些自动化的修改,结合浏览器的一些特性,使得我们写一套样式可以自动转为按照比例控制大小,这样就可以解决兼容问题。
解决这个问题有两个关键点, 一、将字体大小转化为rem,本质上就是将绝对的单位转化为相对的单位,rem会根据根元素的字体大小进行自动计算。 二、设置根元素字体大小,按照不同机型计算出根元素字体大小才能最适配当前机型。
以上两点分别由:px2rem-loader和自定义方法完成。
{
test:/.less$/,
use: [
'style-loader',
'css-loader',
'less-loader',
{
loader: 'px2rem-loader',
options: {
remUnit: 75,
remPrecision: 8
}
}
]
}
// 计算页面根元素字体size
var width = window.innerWidth / 375 * 16 + 'px';
静态资源内联
静态资源内联的含义就是将一些通用的资源做成通用库,然后借助工具将他们内联进html的对应代码。这个工具在webpack中可以是loader也可以是plugin,比较简单,通常可以用row-loader。
sourcemap
sourcemap一般不建议在生产环境中使用,如果确实需要排查问题,建议将其上传到cdn中去,这样的话不会影响正常的业务包的大小。
TreeShaking
treeShaking在webpack中是默认开启的,且仅支持新版本的ES语法。他会将代码中没有使用到的部分‘摇掉’,不会进行打包。 主要运用了es6模块的静态引入的特点进行功能实现。 摇树会作用于没有用到的模块、方法和变量。
代码分割
在webpack中有一个特别重要的配置,叫做optmization,这个配置可以用来将公用的代码抽取出来同时支持将过大的chunk分割成小的chunk。从而起到减小chunk体积的作用,是我们常用的代码优化的手段。
{
optmization: {
splitChunks: {
chunks: '进行优化的chunk类型',
minSize: 'chunk的最大体积',
maxSize: 'chunk的最大体积',
minChunks: '拆分前被共享的最小chunk数',
maxAsyncRequests: '按需加载时最大的请求数',
minInitialRequest:'入口点最小并行请求数',
automaticDelimiter: '用来分割名称的符号',
name: 'chunk名称是否保留之前的名称',
cacheGroups:'将分离的代码进行分组,这里的条件完全继承上一层的所有属性'
}
}
}
代码规范
代码规范是我们写好代码的保证,为我们的代码提供了可维护性。 保证代码规范的方式有很对,可以是webpack,也可以使用编辑器插件,但是后者的操作性就差一些。这里就说一下在webpack中如何实现代码规范检查吧。 想让代码规范生效,eslint需要首先设置一个eslintrc文件,这个文件定义了eslint的审核规则。
eslint除了检查代码,也可以帮助开发者自动格式化代码,这个功能是可选的。 同时自动美化代码还可以使用prettier,这是专门用来进行代码规范的工具。 另外,一般会在配合一个husky来进行git配合,设置pre-commit的检查点。 这样,就能在提交之前发现和修改代码中不符合规范的地方。
{
module:{
rules:[
{
test: /.(js|jsx)$/,
use: 'eslint-loader'
}
]
}
}
可以设置这个loader在其他loader之前进行,这一点小伙伴们应该知道怎么设置,不知道的就去查一下文档吧。
总结
自此,webpack基本使用和优化我们都已经学会了,日常使用对于我们来说应该不成问题了。遇到一些打包问题也可以独立分析了。
下一篇预告
本篇文章仅仅是用于抛砖引玉,小伙伴们在这个之上应该可以更多的探索我没有讲到的问题。下一篇文章,我会分享一下如何进行loader和plugin的编写和分享一下webpack原理。希望对小伙伴们有所帮助。