Webpack解析与讲解
一、什么是Webpack?
一个基于node.js的前端模块化/预处理/扁平化处理器。
二、为什么要使用Webpack?
- 解决业务代码中的各种依赖,模块加载,静态文件引入问题(重复依赖/强依赖,阻塞加载,资源整合)
- 使浏览器支持众多样式预处理器(sass, less, stylus)
- 使浏览器支持众多第三方框架与工具(react/vue/angluar)
- 使浏览器支持ECMA5以上的特性和语法
三、Webpack在打包时都做了些什么?
- 生成一个包含入口出口路径模块的compiler类
- 获取抽象语法树(AST),建立模块之间关系(@babel/parser)
- 找出所有依赖模块(@babel/traverse)
- AST 转换为 code(@babel/core 和 @babel/preset-env)
- 递归解析所有依赖项,生成依赖关系图(mainfest.json)
- 重写 require 函数,输出 bundle(即浏览器能够识别的模块)
const fs = require('fs')
const path = require('path')
const options = require('./webpack.config')
const parser = require('@babel/parser')
const traverse = require('@babel/traverse').default
const { transformFromAst } = require('@babel/core') const Parser = {
getAst: path => {
// 读取入口文件
const content = fs.readFileSync(path, 'utf-8')
// 将文件内容转为AST抽象语法树
return parser.parse(content, {
sourceType: 'module'
})
},
getDependecies: (ast, filename) => {
const dependecies = {}
// 遍历所有的 import 模块,存入dependecies
traverse(ast, {
// 类型为 ImportDeclaration 的 AST 节点 (即为import 语句)
ImportDeclaration({ node }) {
const dirname = path.dirname(filename)
// 保存依赖模块路径,之后生成依赖关系图需要用到
const filepath = './' + path.join(dirname, node.source.value)
dependecies[node.source.value] = filepath
}
})
return dependecies
},
getCode: ast => {
// AST转换为code
const { code } = transformFromAst(ast, null, {
presets: ['@babel/preset-env']
})
return code
}
} class Compiler {
constructor(options) {
// webpack 配置
const { entry, output } = options
// 入口
this.entry = entry
// 出口
this.output = output
// 模块
this.modules = []
}
// 构建启动
run() {
// 解析入口文件
const info = this.build(this.entry)
this.modules.push(info)
this.modules.forEach(({ dependecies }) => {
// 判断有依赖对象,递归解析所有依赖项
if (dependecies) {
for (const dependency in dependecies) {
this.modules.push(this.build(dependecies[dependency]))
}
}
})
// 生成依赖关系图
const dependencyGraph = this.modules.reduce(
(graph, item) => ({
...graph,
// 使用文件路径作为每个模块的唯一标识符,保存对应模块的依赖对象和文件内容
[item.filename]: {
dependecies: item.dependecies,
code: item.code
}
}),
{}
)
}
build(filename) {
const { getAst, getDependecies, getCode } = Parser
const ast = getAst(filename)
const dependecies = getDependecies(ast, filename)
const code = getCode(ast)
return {
// 文件路径,可以作为每个模块的唯一标识符
filename,
// 依赖对象,保存着依赖模块路径
dependecies,
// 文件内容
code
}
}
// 重写 require函数,输出bundle
generate() {}
} new Compiler(options).run()
四、主要涉及知识点:
- require/import
- AMD/CMD
- babel与loader
- require与import
- require是一个同步动态加载,导出的是当前整个模块(一次导出多次使用)
const fs = require('fs') // 其中require的路径是支持模版语法的
console.log(JSON.stringify(fs.readFileSync)
- import是一个同步静态加载,导出的是模块引用(即实现部分导出)
import { addSum } from './path'
addSum()
webpack最终打出的来的包 还是通过babel降维得到的通过amd/cmd规范组合的require包。
- AMD与CMD(异步加载)
- AMD(Async Module Definition) 异步模块定义(require.js)
define(['./a', './b'], function([a,b])) {
a.doSomething()
b.doSomething()
}
依赖前置、在定义模块的时候就要声明其依赖的模块
- CMD(Common Module Definition) 通用模块定义(sea.js)
define(function(require, exports, module) {
var a = require('./a')
a.doSomething()
var b = require('./b')
b.doSomething()
})
就近依赖、只有在用到某个模块的时候再去加载
- babel(Babel 是一个 JavaScript 编译器)
由于浏览器的支持速度远远慢于语言的更新速度。所以我们需要一个强大的能够向下兼容的编译器来帮助浏览器识别我们使用的这些新特性。包括:
- 语法转换
- 通过 Polyfill 方式在目标环境中添加缺失的特性
- 源码转换 (codemods)
eg:
// Babel 输入: ES2015 箭头函数
[1, 2, 3].map((n) => n + 1); // Babel 输出: ES5 语法实现的同等功能
[1, 2, 3].map(function(n) {
return n + 1;
});
我们现在使用到的很多特性/预设/插件/配置/工具等 都是在有babel这个生态中维护(具体可以参考官网 https://www.babeljs.cn/docs/options)
五、要优化Webpack可以怎么做?
分析 :
BundleAnalyzerPlugin
Speed-measure-webpack-plugin
- 优化加载静态资源的大小
(1) 将资源上传至服务器
(2) 开启gzip
(3) 压缩静态资源(图片剔除sourcemap, 代码内容格式化)
(4) 剔除重复的静态资源
- 优化加载(同步/异步)依赖模块的多少
(1) 合理划分同步加载/异步加载模块(包括路由,依赖,以及第三方库等)
(2) 尽量使用按需加载,减少依赖重复引用
(3) 剔除不必要的第三方依赖
(4) 配置跳过一些大的第三方依赖babel-loader
- 添加缓存(manfest.json / babel-loader)
推荐hardSource(webpack 5.0) 与 webpack(4.0) babel-cache
- 启用并行构建(thread-loader)
(1)注意构建时间:(改进前)
(2)注意构建时间:(改进后)
Webpack解析与讲解的更多相关文章
- webpack详细配置讲解
//常见的Webpack配置文件var webpack = require('webpack');var HtmlWebpackPlugin = require('html-webpack-plugi ...
- webpack解析(1)
webpack是为现代js程序准备的静态模块打包工具 一:关于对webpack的理解 可以将其认为是一个电脑主板,由于使用js作为源码,因而其可以默认编译js代码(别种类型的文件可以依靠loaders ...
- 如何使用webpack打包前端项目
webpack概述 随着前端体积越来越大,功能越来越丰富,这时候就需要将前端工程化,而 webpack就是用于将前端各种文件打包起来. 一个简单的webpack应该包含以下几个概念 · 入口起点 · ...
- webpack详解
webpack是现代前端开发中最火的模块打包工具,只需要通过简单的配置,便可以完成模块的加载和打包.那它是怎么做到通过对一些插件的配置,便可以轻松实现对代码的构建呢? webpack的配置 const ...
- vue - webpack、babel
一.webpack 在这里我仅仅的是对webpack做个讲解,webpack这个工具非常强大,解决了我们前端很繁琐的一些工具流程繁琐的事情.如果感兴趣的同学,建议还是看官网吧. 中文链接地址:http ...
- webpack4.x最详细入门讲解
前言 本文主要从webpack4.x入手,会对平时常用的Webpack配置一一讲解,各个功能点都有对应的详细例子,所以本文也比较长,但如果你能动手跟着本文中的例子完整写一次,相信你会觉得Webpack ...
- android基础(五)网络数据解析方法
在网络上传输数据时最常用的方法有两种:XML和JSON,下面就对这两种类型的数据解析进行讲解. 一.XML数据解析 在Android中,常见的XML解析器分别为SAX解析器.DOM解析器和PULL解析 ...
- PULL解析XML的运行机制详解
PULL解析简单易上手,基本上看一遍,基本上就会解析啦,但总是感觉对PULL解析的运行机制不是很了解,就总结了以下事件驱动到底是怎么执行的.. PULL: Android内置了PULL解析器.PULL ...
- iOS开发之JSON格式数据的生成与解析
本文将从四个方面对IOS开发中JSON格式数据的生成与解析进行讲解: 一.JSON是什么? 二.我们为什么要用JSON格式的数据? 三.如何生成JSON格式的数据? 四.如何解析JSON格式的数据? ...
- 前后端分离之vue2.0+webpack2 实战项目 -- webpack介绍
webpack的一点介绍 Webpack 把任何一个文件都看成一个模块,模块间可以互相依赖(require or import),webpack 的功能是把相互依赖的文件打包在一起.webpack 本 ...
随机推荐
- 20_webpack_shimming预支全局变量和css的抽离
shimming是什么 shimming 是一个概念,是某一些功能的统称 shimming(垫片),给我们的代码填充一些垫片来处理一些问题 比如我们现在以来一个第三方的库,这个第三方的库本身依赖lod ...
- Didn't find class "org.apache.http.ProtocolVersion
使用volley时报"Didn't find class "org.apache.http.ProtocolVersion" 今天在运行签名好的apk 在android9 ...
- 51电子-STC89C51开发板:汇编教程
全部内容请点击目录列表查看: 51电子-STC89C51开发板:<目录> --------------------------- 正文开始 ---------------------- ...
- 51电子-STC89C51开发板:安装KEIL
全部内容,请点击: 51电子-STC89C51开发板:<目录> --------------------------- 正文开始 --------------------------- ...
- [已解决]Android studio连接远程MySQL问题解决
我电脑安装的是8.0的MySQL,导入使用的jar包是mysql-connector-java-5.0.7 1.首先先按照大佬的链接配置好一些东西,注意!已经安装8.0版本MySQL的保持原样就行,不 ...
- 树莓派,脚本遍历当前目录下视频文件,并用omxplayer播放
事先准备好视频文件,文件名内包含视频尺寸信息,以方便构造 --win "x1 y1 x2 y2" 字符串. 通过 omxplayer -i filename 可查看视频尺寸 ...
- Mybatis缓存(3)
10.4.3二级缓存
- java基础(一)~~内存分析
1.java内存分析 2.2.面向对象内存分析 Java虚拟机的内存可以分为三个区域:栈(stack).堆(heap).方法区(method area): 2.2.1.栈 栈的特点如下: 1.栈描述的 ...
- 你的ASP.NET Pages项目编译时为何总是很慢慢慢~?
摘要 很多同学在运行同一个Asp.net Pages项目解决方案时会发现,有时候很快,有时候超级慢,甚至时间超过10几分钟才可以完全编译完,随后才能调试! 其实这都是跟配置有关 有句话说的话,约定 ...
- ksfitappUI自动化(准备+安装环境)
一.原理+安装 https://blog.csdn.net/weixin_30624825/article/details/94803252 https://www.kancloud.cn/guanf ...