一、什么是Webpack?

  一个基于node.js的前端模块化/预处理/扁平化处理器。

二、为什么要使用Webpack?

  1. 解决业务代码中的各种依赖,模块加载,静态文件引入问题(重复依赖/强依赖,阻塞加载,资源整合)
  2. 使浏览器支持众多样式预处理器(sass, less, stylus)
  3. 使浏览器支持众多第三方框架与工具(react/vue/angluar)
  4. 使浏览器支持ECMA5以上的特性和语法

三、Webpack在打包时都做了些什么?

  1. 生成一个包含入口出口路径模块的compiler类
  2. 获取抽象语法树(AST),建立模块之间关系(@babel/parser)
  3. 找出所有依赖模块(@babel/traverse)
  4. AST 转换为 code(@babel/core 和 @babel/preset-env)
  5. 递归解析所有依赖项,生成依赖关系图(mainfest.json)
  6. 重写 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()

四、主要涉及知识点:

  1. require/import
  2. AMD/CMD
  3. babel与loader

- require与import

  1. require是一个同步动态加载,导出的是当前整个模块(一次导出多次使用)
 const fs = require('fs') // 其中require的路径是支持模版语法的
console.log(JSON.stringify(fs.readFileSync)
  1. import是一个同步静态加载,导出的是模块引用(即实现部分导出)
import { addSum } from './path'
addSum()

  webpack最终打出的来的包 还是通过babel降维得到的通过amd/cmd规范组合的require包。

- AMD与CMD(异步加载)

  1. AMD(Async Module Definition) 异步模块定义(require.js)
  define(['./a', './b'], function([a,b])) {
a.doSomething()
b.doSomething()
}

  依赖前置、在定义模块的时候就要声明其依赖的模块

  1. 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 编译器)

由于浏览器的支持速度远远慢于语言的更新速度。所以我们需要一个强大的能够向下兼容的编译器来帮助浏览器识别我们使用的这些新特性。包括:

  1. 语法转换
  2. 通过 Polyfill 方式在目标环境中添加缺失的特性
  3. 源码转换 (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. 优化加载静态资源的大小

    (1) 将资源上传至服务器

    (2) 开启gzip

    (3) 压缩静态资源(图片剔除sourcemap, 代码内容格式化)

    (4) 剔除重复的静态资源

  2. 优化加载(同步/异步)依赖模块的多少

    (1) 合理划分同步加载/异步加载模块(包括路由,依赖,以及第三方库等)

    (2) 尽量使用按需加载,减少依赖重复引用

    (3) 剔除不必要的第三方依赖

    (4) 配置跳过一些大的第三方依赖babel-loader

  3. 添加缓存(manfest.json / babel-loader)

    推荐hardSource(webpack 5.0) 与 webpack(4.0) babel-cache

  4. 启用并行构建(thread-loader)

   (1)注意构建时间:(改进前)

  (2)注意构建时间:(改进后)

Webpack解析与讲解的更多相关文章

  1. webpack详细配置讲解

    //常见的Webpack配置文件var webpack = require('webpack');var HtmlWebpackPlugin = require('html-webpack-plugi ...

  2. webpack解析(1)

    webpack是为现代js程序准备的静态模块打包工具 一:关于对webpack的理解 可以将其认为是一个电脑主板,由于使用js作为源码,因而其可以默认编译js代码(别种类型的文件可以依靠loaders ...

  3. 如何使用webpack打包前端项目

    webpack概述 随着前端体积越来越大,功能越来越丰富,这时候就需要将前端工程化,而 webpack就是用于将前端各种文件打包起来. 一个简单的webpack应该包含以下几个概念 · 入口起点 · ...

  4. webpack详解

    webpack是现代前端开发中最火的模块打包工具,只需要通过简单的配置,便可以完成模块的加载和打包.那它是怎么做到通过对一些插件的配置,便可以轻松实现对代码的构建呢? webpack的配置 const ...

  5. vue - webpack、babel

    一.webpack 在这里我仅仅的是对webpack做个讲解,webpack这个工具非常强大,解决了我们前端很繁琐的一些工具流程繁琐的事情.如果感兴趣的同学,建议还是看官网吧. 中文链接地址:http ...

  6. webpack4.x最详细入门讲解

    前言 本文主要从webpack4.x入手,会对平时常用的Webpack配置一一讲解,各个功能点都有对应的详细例子,所以本文也比较长,但如果你能动手跟着本文中的例子完整写一次,相信你会觉得Webpack ...

  7. android基础(五)网络数据解析方法

    在网络上传输数据时最常用的方法有两种:XML和JSON,下面就对这两种类型的数据解析进行讲解. 一.XML数据解析 在Android中,常见的XML解析器分别为SAX解析器.DOM解析器和PULL解析 ...

  8. PULL解析XML的运行机制详解

    PULL解析简单易上手,基本上看一遍,基本上就会解析啦,但总是感觉对PULL解析的运行机制不是很了解,就总结了以下事件驱动到底是怎么执行的.. PULL: Android内置了PULL解析器.PULL ...

  9. iOS开发之JSON格式数据的生成与解析

    本文将从四个方面对IOS开发中JSON格式数据的生成与解析进行讲解: 一.JSON是什么? 二.我们为什么要用JSON格式的数据? 三.如何生成JSON格式的数据? 四.如何解析JSON格式的数据? ...

  10. 前后端分离之vue2.0+webpack2 实战项目 -- webpack介绍

    webpack的一点介绍 Webpack 把任何一个文件都看成一个模块,模块间可以互相依赖(require or import),webpack 的功能是把相互依赖的文件打包在一起.webpack 本 ...

随机推荐

  1. day11 事件相关笔记

    day11 事件上 事件的概述 事件是指代一个东西的操作被另外一个东西监听以后的一个过程(事件),这个过程可以完成对应的操作(处理函数)事件监听器是一个标准的观察者模式(observer)也被称为订阅 ...

  2. Linux装cudnn

    https://stackoverflow.com/questions/66977227/could-not-load-dynamic-library-libcudnn-so-8-when-runni ...

  3. 6.mysql优化案例

    1.单表优化:  进行优化: 删除原来的三个字段的索引,创建二个字段的索引: 2.两表关联: 左连接,在右表创建索引   右连接,在左表创建索引: 3.三表关联:左关联全都在右表创建索引:

  4. C# 数据结构之嵌套加法、嵌套乘法

    复杂性度量问题 1.大O复杂度:嵌套加法 找出以下代码片段的 Big O 复杂度. using System; namespace Chapter_1 { class Challenge_1 { st ...

  5. Linux下clang、gcc、intel编译器最新版本安装笔记

    转自 http://t.zoukankan.com/opangle-p-2838554.html

  6. python中items()和iteritems()的区别

    items()函数,将一个字典以dict_items的形式返回,因为字典是无序的,所以返回的列表也是无序的: 1 a ={'a':1,'b':2,'c':3,'d':4} 2 print(a.item ...

  7. Impala 学习笔记

    VALUES Statement | 6.3.x | Cloudera Documentation SELECT now() as date_DES UNION ALL SELECT trunc(no ...

  8. J V M(二)双亲委派机制及native

    package java.lang;public class String {// 双亲委派机制: 安全// 应用程序加载器-扩展程序加载器-根加载器// 自底向上检查类是否被加载,自顶向下加载类// ...

  9. 03 Proxmox VE介绍

    突破困境! 企业开源虚拟化管理平台 使用Proxmox Virtual Environment 郑郁霖(Jason Cheng)著 版次:2021年12月初版 03 Proxmox VE介绍 3.1 ...

  10. c原因学习---指针作为函数的形参

    指针作为函数的形参, 可以改变实参的值. #include<stdio.h> // 交换两个变量的值 int swap(int x, int y) { int k = y; y = x; ...