webpack引入 | 青训营笔记

60 阅读4分钟

这是我参与「第四届青训营 」笔记创作活动的第5天

为什需要webpack

1. 在浏览器引入js脚本的方式有:

<!-- 引入外部的 JavaScript 文件 -->
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<!-- 引入我自己的 JavaScript 文件 -->
<script src="./scripts/common.js"></script>     
复制代码

此解决方案很难扩展,因为加载太多脚本会导致网络瓶颈。同时如果你不小心更改了JavaScript文件的 加载顺序 ,这个项目可能要崩溃;一般在页面内有多个js文件且顺序颠倒可能导致bug,特别是最上面还有有引入 jquery / lodash / bootstrap 之类的外部库及框架文件时 存在依赖

自己引入一个js文件内嵌多个文件的引入会导致:

  1. 作用域问题

    • 库文件在window下绑定全局变量如 $ _ 之类,本身用户文件也会绑定全局变量,会导致污染
  2. 文件太大

    • 需要一段时间加载,会导致短暂的白屏;(拆开会随文件解析慢慢加载出一个一个部分)
  3. 可读性差

  4. 可维护性弱

2. 解决作用域问题:

在早期使用Grunt和Gulp两个工具来管理我们项目的资源

  • 任务执行器 :将所有的项目文件拼接在一起(利用了js的立即调用函数表达式(IIFE) - Immediately invoked function expressions)解决了大型项目的作用域问题;当脚本文件被封装在 IIFE 内部时,你可以安全地拼接或安全地组合所有文件,而不必担心作用域冲突。基本操作原理如下:
    ; (function () {  // 开头多加个;避免压缩后出现问题
         var myName = "千锋大前端"
    })()
    // 当数变成立即执行的函数表达式时,表达式中的变量不能从外部访问。
    // 不会污染window环境,解决了作用域问题
    // *闭包
    // 将其赋给一个变量=>储存执行返回的结果
    var result = (function () {
         var myName = "千锋大前端"
         return myName
        // 通过return来暴漏需要的数据=>多的可以用对象传递
    })()
    console.log(result) //输出暴漏的数据
复制代码
  • Grunt , Gulp 解决了作用域问题。但是,修改一个文件意味着必须重新构建整个文件。拼接可以做到很容易地跨文件重用脚本,却使构建结果的优化变得更加困难。如何判断代码是否实际被使用? 
  • 即使你只用到 lodash 中的某个函数,也必须在构建结果中加入整个库,然后将它们压缩在一起。大规模地实现延迟加载代码块及无用代码的去除,需要开发人员手动地进行大量工作。

3. 如何解决代码拆分问题

  • Node.js 是一个 JavaScript 运行时,可以在浏览器环境之外的计算机和服务器中使用。webpack 运行在 Node.js 中。

  • 当 Node.js 发布时,一个新的时代开始了,它带来了新的挑战。既然不是在浏览器中运行 JavaScript,现在已经没有了可以添加到浏览器中的 html 文件和 script 标签。那么 Node.js 应用程序要如何加载新的代码文件呢?

    • CommonJS 问世并引入了 require 机制,它允许你在当前文件中加载和使用某个模块。导入需要的每个模块,这一开箱即用的功能,帮助我们解决了代码拆分的问题。
    • Node.js 已经成为一种语言、一个平台和一种快速开发和创建快速应用程序的方式,接管了整个 JavaScript 世界。
    • 但 CommonJS 没有浏览器支持。没有 live binding(实时绑定)。循环引用存在问题。同步执行的模块解析加载器速度很慢。虽然 CommonJS 是 Node.js 项目的绝佳解决方案,但浏览器不支持模块化

4. 如何让浏览器支持模块

  • 在早期,我们应用 Browserify 和 RequireJS 等打包工具编写能够在浏览器中运行的commonJS模块 【具体操作原理参考require.js提供的require( )方法】
  • 目前,我们还有一个选择,就是来自 Web 项目的好消息是,模块正在成为ECMAScript 标准的官方功能。然而,浏览器支持不完整,版本迭代速度也不够快,还是推荐上面两个早期模块实现。早期的任务构建工具基于 Google 的 Closure 编译器,要求我们手动在顶部声明所有的依赖,开发体验不好

5. 利用webpack来实现这一切 

  • webpack不仅可以让我们编写模块,而且还支持任何模块格式(至少在我们到达 ESM 之前),并且可以同时处理 resource 和 assets ;
  • 可以打包你的 JavaScript 应用程序(支持 ESM和 CommonJS),可以扩展为支持许多不同的静态资源,例如:images , fonts 和 stylesheets ;
  • webpack 关心性能和加载时间;它始终在改进或添加新功能,例如:异步地加载和预先加载代码文件,以便为你的项目和用户提供最佳体验

image.png