深入浅出webpack系列解读(1)
相信从事前端开发的小伙伴们一定听过webpack,但是很多人对webpack的认知仅仅停留在npm run build
然后出一个dist文件夹,而并不了解webpack实际上大有所为
面试官问你了解webpack的啥,你大概也只能说出一二就草草了之( Ꙭ)
这一系列的文章就带你来领略webpack之美、之博大精深,我会尽可能地用简洁精炼的语言来总结webpack的学习重点,大家可以放心食用~
先放一个目录,这一个系列大概会总结下来的几个部分
遵循的认知学习模式是,从 应用 到 理解 再到 造轮子
入门 重在教你如何使用webpack
配置 在框架中的实战应用、构建离线应用、加载图片SVG等
优化 缩小文件的搜索范围、自动刷新、开启模块热更新、使用Tree Shaking等
原理 编写Loader、Plugin、调试webpack等
好啦,接下来那就让我们来开启webpack的大门吧~
模块化
在认识webpack之前,我们需要了解一个很重要的概念模块化
模块化是指将一个复杂的系统分解为多个模块以方便编码
就好比我们面临一个巨大的仓库,里面存放了各种各样的物品,各物品之间相互关联,而我们如果不借助任何工具整理起来会很困难,但此时我们如果将物品分成一个个模块来整理,就会轻松很多
然而我们还需要了解的是,在不同的环境下,我们需要用到的模块化标准不同
CommonJS
node.js中采用的就是这种规范,写过node的同学应该都知道
核心思想:
通过require方法来同步加载依赖的其他模块,通过module.exports导出需要暴露的接口
采用CommonJS导入及导出的代码如下:
//导入
const moduleA = require('./moduleA');
//导出
module.exports = moduleA.someFunc;
CommonJS的优点
-
代码可复用性高
-
基于node.js环境下运行
-
通过npm发布的很多第三方模块都采用了这个规范
CommonJS的缺点
CommonJS的缺点主要在于,这样的代码无法直接在浏览器环境下运行,必须通过工具转换成标准的ES5
AMD
AMD规范和CommonJS最大的不同就是,它采用了异步的方式去加载依赖的模块
// 定义一个模块
define('module', ['dep'], function (dep) {
return exports;
});
//导入和使用
require(['module'], function (module) {
});
这种javascript模块化规范可以直接在浏览器中运行,还可以并行加载多个依赖,不过需要导入像requirejs这样的库之后才可以正常使用
ES6模块化
从ES6 开始,JavaScript
原生引入了模块概念,而且现在主流浏览器也都有了很好的支持,而在ES6模块化中,一个文件就是模块,拥有独立的作用域,且导出的模块都自动处于 严格模式
下,即:'use strict'
导入分为两种模式
- 静态导入
- 动态导入
静态导入
在浏览器中,import
语句只能在声明了 type="module"
的 script 的标签中使用。
import defaultExport from "module-name";
import * as name from "module-name";
import { export } from "module-name";
import { export as alias } from "module-name";
import { export1 , export2 } from "module-name";
import { foo , bar } from "module-name/path/to/specific/un-exported/file";
import { export1 , export2 as alias2 , [...] } from "module-name";
import defaultExport, { export [ , [...] ] } from "module-name";
import defaultExport, * as name from "module-name";
import "module-name";
静态导入方式不支持延迟加载,import
必须这模块的最开始
document.onclick = function () {
// import 必须放置在当前模块最开始加载
// import m1 from './m1.js'
// console.log(m1);
}
动态导入
此外,还有一个类似函数的动态 import()
,它不需要依赖 type="module"
的 script 标签。
关键字 import
可以像调用函数一样来动态的导入模块。以这种方式调用,将返回一个 promise
。
import('./m.js')
.then(m => {
//...
});
// 也支持 await
let m = await import('./m.js');
通过 import()
方法导入返回的数据会被包装在一个对象中,即使是 default
也是如此
构建内核
如今前端生态已经越来越复杂多样,各种框架技术层出不穷,但源代码都不能直接运行,必须通过转换后才可以正常运行,比如vue的语法,其实是不能直接拿到浏览器里面去运行的,浏览器能识别的代码只有html、css和js
所以我们不难理解,所谓构建做的就是这样一件事情,将源代码转换成可执行的html、css和javascript代码,具体包括以下几个内容:
-
代码转换:将TS编译成js、将scss编译成css等
-
文件优化:压缩js、css、html代码、压缩合并图片
-
代码分割:提取多个页面的公共代码,提取首屏不需要执行部分的代码让其异步加载
-
模块合并:在采用模块化的项目里会有很多个模块和文件,需要通过构建功能将模块分类合并成一个文件(就像我前面举的仓库整理的栗子)
-
自动刷新:在代码被提交到仓库前需要校验代码是否符合规范,以及单元测试是否通过
-
自动发布:更新代码后,自动构建出线上发布代码并传输给发布系统
构建为前端注入了更大的活力,解放了我们的生产力,看到这里,大家应该已经意识到webpack做的事情远比我们想象的多得多
其实过去包括现在,有许许多多这样的构建工具,gulp、grunt等等包括现在起来的vite,但webpack还是目前为止难以打败的神作,所以我们学习它只能说稳赚不亏~(˶‾᷄ꈊ‾᷅˵)~
初识webpack
官网的描述是这样的webpack 是一个用于现代 JavaScript 应用程序的 静态模块打包工具
在webpack中一切文件皆是模块,当然包括图片文件、文本文件等等,然后通过loader转换文件,通过plugin注入钩子,最后输出多个由模块组合成的文件
初来的小伙伴们现在可能还不理解什么是loader和plugin,没关系后面我会有详细的介绍和总结,大家先在这里留个心眼,这俩是webpack中很重要的组成部分
loader就是比如说,现在有一个文本文件txt,但导入模块的时候,只能识别js,那么要怎么把文本文件转换成能识别的js文件呢,这时候就需要用到loader了
而plugin负责解决loader无法解决的问题,是一个功能更强大、灵活度更高的工具
我们来看看webpack有什么优点
-
专注于处理模块化项目,能做到开箱即用、一步到位
-
可以通过plugin扩展,完整好用又不失灵活
-
使用场景不局限于web开发
-
爽翻天的开发体验
-
……
哈哈,我只能说对webpack赞不绝口ʕु•̫͡•ʔु ✧
安装webpack
首先确保你的电脑安装了v5.0.0以上的Node.js
在开始为项目加入构建前,需要新建一个web项目,有如下方式:
- 新建一个目录,再进入项目根目录执行npm init来初始化最简单的采用了模块化开发的项目
- 用脚手架工具直接/快速生成一个最符合自己需求的项目(比如vue-cli)
安装webpack到本项目
第一步
npm i -D
即 npm install --sava-dev
的缩写
或者我们在拉取了他人的项目之后习以为常的npm install
操作,即安装模块并保存到package.json的devDependencies
第二步
安装最新的稳定版本npm i -D webpack
安装webpack到全局
执行命令npm i -g webpack
,安装到全局之后,我们可以在任何项目共用一个webpack可执行文件,但还是推荐大家安装webpack到局部,因为不同项目之间的依赖版本可能存在差异,避免引起不必要的报错
最后,整理的部分知识小节送给大家~
后期会持续输出webpack系列文章,欢迎大家点赞关注~ฅ՞•ﻌ•՞ฅ
我是dazzlingwen,热爱前端的小小白,期待也和我同样热爱前端的小伙伴们一起进步、一起成长~
转载自:https://juejin.cn/post/7140265534574034958