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');// 语法解析成 ASTconst 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