为啥要使用 WebPack?

Posted

技术标签:

【中文标题】为啥要使用 WebPack?【英文标题】:Why use WebPack?为什么要使用 WebPack? 【发布时间】:2019-08-11 03:43:33 【问题描述】:

我花了几天时间让 Webpack 启动并运行,并且刚刚进行了测试。但是我发现 webpack 中的 bundle.js 文件做了很多对我来说没有意义的不必要的事情。

index.js

import greet from './greet';

console.log("I'm the entry point");
greet();

greet.js

function greet() 
    console.log('Have a great day!');
;

export default greet;

超级简单。但是 bundle.js

!(function(e) 
  var t = ;
  function n(r) 
    if (t[r]) return t[r].exports;
    var o = (t[r] =  i: r, l: !1, exports:  );
    return e[r].call(o.exports, o, o.exports, n), (o.l = !0), o.exports;
  
  (n.m = e),
    (n.c = t),
    (n.d = function(e, t, r) 
      n.o(e, t) || Object.defineProperty(e, t,  enumerable: !0, get: r );
    ),
    (n.r = function(e) 
      "undefined" != typeof Symbol &&
        Symbol.toStringTag &&
        Object.defineProperty(e, Symbol.toStringTag,  value: "Module" ),
        Object.defineProperty(e, "__esModule",  value: !0 );
    ),
    (n.t = function(e, t) 
      if ((1 & t && (e = n(e)), 8 & t)) return e;
      if (4 & t && "object" == typeof e && e && e.__esModule) return e;
      var r = Object.create(null);
      if (
        (n.r(r),
        Object.defineProperty(r, "default",  enumerable: !0, value: e ),
        2 & t && "string" != typeof e)
      )
        for (var o in e)
          n.d(
            r,
            o,
            function(t) 
              return e[t];
            .bind(null, o)
          );
      return r;
    ),
    (n.n = function(e) 
      var t =
        e && e.__esModule
          ? function() 
              return e.default;
            
          : function() 
              return e;
            ;
      return n.d(t, "a", t), t;
    ),
    (n.o = function(e, t) 
      return Object.prototype.hasOwnProperty.call(e, t);
    ),
    (n.p = ""),
    n((n.s = 0));
)([
  function(e, t, n) 
    "use strict";
    n.r(t);
    var r = function() 
      console.log("Have a great day!");
    ;
    console.log("I'm the entry point"), r();
  
]);

似乎 WebPack 做了很多对我来说毫无意义的不必要的代码。 bundle.js 的文件大小也是 index.js 和 greet.js 的 3 倍。对于如此简单的事情,应用程序的开发构建也看起来非常混乱和混乱。

那么我为什么要继续花时间在我的项目中使用 WebPack? 它输出的所有额外代码是什么,为什么会在那里? 是否有更好的替代方案可以帮助我从模块化开发环境中发布代码?

非常感谢您帮助我理解为什么我应该或不应该使用 WebPack。

谢谢!

【问题讨论】:

在没有任何捆绑的情况下用 React 编写一个大型应用程序,看看你的进展如何:) 【参考方案1】:

bundle.js 的文件大小也是 index.js 和 greet.js 的 3 倍

Webpack 必须为浏览器无法处理的事情添加一些 polyfill,例如模块加载。如果你有 2 行代码,这些 polyfill 看起来很繁重,但是如果你写了数千行代码,你不会注意到任何显着的开销,因为这些 poyfill 只添加了一次。

那么我为什么要继续花时间在我的项目中使用 WebPack?

因为它会为大型项目生成更小的包,它还允许您编写 ESnext 和干净的模块化代码。

它输出的所有额外代码是什么,为什么会在那里?

它保持全局范围干净,添加一些帮助器和模块加载器,然后加载第一个模块:

// IIFE to keep global scope clean, ! to prevent Automatic Semicolon Insertion fun
!(function init(modules) 
  var cache = ; // cache the modules results
  // All modules are in an array, their index is a unique identifier
  function require/*n*/(index/*r*/) 
    if (cache[index]) return cache[index].exports;
    var context/*o*/= (cache[index =  index/*i*/: index, loaded/*l*/: false/*!1*/, exports:  );

    modules[index].call(
      context.exports, 
      context,
      context.exports, 
      require
    );
    context.loaded = true /*!0*/;
    return context.exports;
  

  require.modules = modules; // I'm not sure why?...
  require.cache = cache;

  // helper for adding a getter
  require.addGetter /*n.d*/ = function(object, key, getter) 
    require.has(object, key) || Object.defineProperty(object, key,  enumerable: true, get: getter );
  );

  require.prepareExport /*n.r*/ = function(export) 
    if("undefined" != typeof Symbol && Symbol.toStringTag)
      Object.defineProperty(export, Symbol.toStringTag,  value: "Module" );

    Object.defineProperty(export, "__esModule",  value: true );
  ;

 // I have no idea what that is doing

  require.startModule /*n.s*/ = 0;
  require(require.startModule); // start execution
)([
  /* Your modules, identified by index */
  function mainModule(context, exports, require) 
      "use strict"; // better performance
      require.prepareExport(export); // as you could override exports in your module, this has to be called afterwards

     var otherModule = function()  // inlined!
        console.log("Have a great day!");
     ;

    console.log("I'm the entry point"), 

    otherModule();
   /* ... more modules would follow here if not inlined */
]);

是否有更好的替代方案可以帮助我从模块化开发环境中发布代码?

有替代品,不确定它们是否“更好”。

【讨论】:

【参考方案2】:

我同意 Webpack 增加了很多你可能不需要的东西。它还有这个疯狂的配置文件,简直就是疯狂。

为简单起见,您可以只加载带有脚本标签的模块文件,然后将 Webpack 扔出窗口! (仅在现代浏览器中 (Edge16+, FF60+, Chrome61+,Safari11+))。

<script type="module" src="greet.js">
<script type="module" src="app.js">

您还可以使用更简单的 webpack 替代品,例如 ParcelJS 或 Rollup。这些编译器都可以做很多事情,这取决于你需要什么:

将你的模块打包成一个大的旧bundle.js文件 使代码与旧版浏览器兼容。 将 scss 转换为 css,将 typescript 转换为 javascript 等。 使用自动重新加载启动开发服务器 构建整个网站文件夹,仅包括项目中实际使用的文件。

【讨论】:

"你可以只用脚本标签加载你的模块文件,然后把 Webpack 扔出窗口" - 或者更现实地说,你可以使用一个打包器来生成包,这些包可以是现代和旧版浏览器都在使用。 “现实”取决于上下文。如今,并非每个项目都必须在 IE8 上运行。但是,是的,我不会说您不需要捆绑器。如果您正在学习 javascript 基础知识和模块,则不需要它。【参考方案3】:

我已经与打包者进行了相当多的战斗。还有其他方法。经过几年的经验和反复试验,我想出的最佳选择是我的项目 Zwitterion:https://github.com/lastmjs/zwitterion

它被设计为替代静态文件服务器的交换。它支持 ES2015+、TypeScript、AssemblyScript、Rust、C、C++,并且可能很快会支持 JSX、TSX 和 Vue。您不必更改文件结构或直观的开发方式。只需编写您的源代码,将其包含在脚本元素或模块导入中,它就可以工作了。

【讨论】:

以上是关于为啥要使用 WebPack?的主要内容,如果未能解决你的问题,请参考以下文章

任务运行程序(Gulp、Grunt 等)和捆绑程序(Webpack、Browserify)。为啥要一起使用?

为啥 Webpack 4 不创建 dist 文件夹,而 webpack 2 却创建?

为啥有些使用typescript/webpack的项目也使用babel完成编译

为啥 Tailwind 中的清除选项不能与 Webpack 一起使用

webpack 打包和手动创建一个vue的项目

为啥 tailwindcss 没有在 webpack 中使用 sass 文件正确导入所有组件?