5 minutes read

Nodejs的webpack是什么, 作用是什么, 怎么实现的, 优势是什么, 劣势是什么


Fire bug
13/11/2022 10:40 PM

大白话系列之:去除webpack的神秘面纱!

webpack是什么, 作用是什么

官网定义:本质上, webpack 是一个现代 JavaScript 应用程序的静态模块打包器(module bundler)。

源码:https://github.com/webpack/webpack

工作方式:webpack会递归地构建一个依赖关系图(dependency graph), 其中包含应用程序需要的每个模块, 然后将所有这些模块打包成一个或多个 bundle。简单的来说, WebPack可以看做是模块打包机:它做的事情是, 分析你的项目结构, 找到JavaScript模块以及其它的一些浏览器不能直接运行的拓展语言(Scss, TypeScript等), 并将其打包为合适的格式以供浏览器使用。在开发蜂巢指纹浏览器(NestBrowser)就不可避免需要深入理解webpack。

webpack怎么实现的

源码太复杂, 分析起来太麻烦。用一个简单的实现来说明实现原理最有效。

webpack的核心功能分为两步:

1、分析入口js文件, 把所有的依赖找出来(包括所有后代的依赖)。其中依赖babel生成AST抽象语法树。次案例我们用的是babel的配套工具来做语法分析和转化, 但是真正的webpack用的是webassemblyjs的配套工具。

webassemblyjs官网:https://webassembly.js.org/

源码:https://github.com/xtuc/webassemblyjs

const fs = require('fs');
const path = require('path');
const parser = require('@babel/parser');
const traverse = require('@babel/traverse').default;
const { transformFromAST } = require('@babel/core');
// 分析一个文件, 转成CommonJS Module, 并找出它的依赖
function readCode(filePath) {
// 读取文件字符串
const content = fs.readFileSync(filePath, 'utf-8');
// 语法解析成 AST
const ast = parser(content, {
sourceType: 'module'
})
// 获取本文件的依赖
const dependiences = [];
// 遍历 AST, 每当触发依赖钩子, 就往依赖数组添加
traverse(ast, {
ImportDeclaration({node}) {
// 把对应的以来路径存起来
dependiences.push(node.source.value)
}
})
// 把 es6 转成 es5 字符串
// 最重要的是把 esModule 的 import export, 转成 es5 能认识的 commonJs写法
const { code } = transformFromAST(ast, null, {
presets: ['@babel/preset-env']
})
return {
filePath,
code,
dependiences
}
}
// 广度优先算法, 深入找出所有的依赖
function getAllDependencies(filePath) {
const entryObj = readCode(filePath);
const dependencies = [entryObj];
for (const dependency of dependencies) {
const curDirname = path.dirname(dependency.filePath)
for (const relativePath dependency.dependencies) {
const absolutePath = path.join(curDirname, relativePath);
const child = readCode(absolutePath);
child.relativePath = relativePath;
dependencies.push(child);
}
}
return dependencies;
}

2、拼接一个立即执行函数

function bundle(fileName) {
const dependencies = getAllDependencies(fileName);
const modulesStr = '';
dependencies.forEach(dependency => {
const key = dependency.relativePath || dependency.filePath;
modulesStr += `'${key}': function(module, exports, require) {
${ dependency.code }
}`
})
return `(function(modules) {
const installedModules = {};
function require(id) {
// 解决循环依赖
if (installedModules[id]) {
return installedModules[id].exports;
}
var module = installedModules[id] = {exports: {}};
modules[id].call(module.exports, module, module.exports, require);
return module.exports;
}
return require('${fileName}')
})({${modulesStr}})`
}
webpack优势是什么, 劣势是什么

优势:

1、webpack 是以 commonJS 的形式来书写脚本的, 但对 AMD/CMD 的支持也很全面, 方便旧项目进行代码迁移。 2、可以通过配置, 打包成多个文件, 有效利用浏览器的缓存功能提升性能。 3、将样式文件和图片等静态资源也可视为模块进行打包。配合 loader 加载器, 可以支持 Sass, Less 等 CSS 预处理器。 4、专注于处理模块化的项目, 能做到开箱即用、 一步到位。 5、扩展性强, 插件 plugins 机制完善。

利用webpack 蜂巢指纹浏览器(NestBrowser)的可以实现复杂的模块加载和打包。

劣势:

1、配置难&难调试。熟练配置门槛高。错误提示也非常难看懂, 基本不可能从错误很直观的找到原因, 出错的时候需要花费相当大的精力查找问题。

2、编译慢。经验不足的同学很容易碰到这个问题, 当然可以通过一些手段做优化, 比如配置module的resolve、root等, 使用happypack加速、dll提前编译等等。

3、蜂巢指纹浏览器(NestBrowser)开发过程中还遇到一个升级的问题, 确实需要耗费很多精力。


Fire bug

Leader

Nestbrowser(蜂巢浏览器) 可自定义所有参数来隐藏和控制您的数字指纹。您可以模仿真实的 Internet 身份。 Nestbrowser 帮助您创建大量配置文件, 每个配置文件都有自己的数字指纹。这些配置文件彼此不重叠, 因此网站不会禁止您的帐户。这对于执行各种任务非常有用在网上。

Member since Mar 15, 2021


最近文章

React-dnd 实现无限子集的拖拽构建功能(多层嵌套)
15 Jul 202314 minutes read
查看所有文章