WebpackLibrary和LibraryTarget详解

简介

webpack 的 output.libraryTarget 有多种参数,每种参数都会影响最终编译后的文件。笔者在下文中,将结合实际编译完成后的文件,介绍 libraryTarget 对源代码的实际影响。

前言

webpack 官方文档将 libraryTarget 主要分为三类:

  1. Expose a Variable: 暴露为一个变量
  2. Expose Via Object Assignment: 通过对象属性暴露
  3. Module Definition Systems: 模块定义系统

首先我们将 webpack 编译后的文件进行简化,去除模块系统相关的逻辑,只保留最终导出的结果和赋值语句,最后的代码如下:

--- webpack编译后的文件:dist/index.js
// 构建模块函数
function a() {
  ...
  return __webpack_require__(__webpack_require__.s = "./src/index.js");
}
导出 a() // libraryTarget不同,导出语句不同

--- 其他模块
require('dist/index.js');

由于 libraryTarget 只是影响最后的赋值导出操作,所以我们这里假设构建后的模块固定,只通过对比最终的赋值操作,来描述 library 和 libraryTarget 的实际效果。现假设构建后的模块如下所示:

{
  name: 'jack',
  age: 24
}

接下来,笔者将结合该返回值,简化描述编译后的实际代码。

第一类:暴露为一个变量

一、libraryTarget: “var”

webpack 配置:

output: {
  ...
  libraryTarget: 'var',
},

编译后的文件如下所示:

(() => {
  return {
    name: 'jack',
    age: 24,
  };
})();

特点:

  1. 没有赋值操作,所以其他文件没法引用该对象

加了 library 之后的 webpack 配置:

output: {
  ...
  library: 'finalModule',
  libraryTarget: 'var',
},

编译后的文件如下所示:

var finalModule = (() => {
  return {
    name: 'jack',
    age: 24,
  };
})();

特点:

  1. 有赋值操作,赋值给 library 定义的变量。

二、libraryTarget: “assign”

webpack 配置:

output: {
  ...
  libraryTarget: 'assign',
},

编译后的文件如下所示:

 = (() => {
  return {
    name: 'jack',
    age: 24
  }
})()

特点:

  1. 语法错误。可见该值需要绑定 library 属性

加了 library 之后的 webpack 配置:

output: {
  ...
  library: 'finalModule',
  libraryTarget: 'assign',
},

编译后的文件如下所示:

finalModule = (() => {
  return {
    name: 'jack',
    age: 24,
  };
})();

特点:

  1. 赋值给全局变量, 可能会覆盖宿主环境下的同名属性值。

第二类:通过对象属性暴露

一、libraryTarget: “this”

webpack 配置:

output: {
  ...
  libraryTarget: 'this',
},

编译后的文件如下所示:

((e, a) => {
  for (var i in a) {
    e[i] = a[i];
  }
})(
  this,
  (() => {
    return {
      name: 'jack',
      age: 24,
    };
  })()
);

加了 library 之后的 webpack 配置:

output: {
  ...
  library: 'finalModule',
  libraryTarget: 'this',
},

编译后的文件如下所示:

this['finalModule'] = (() => {
  return {
    name: 'jack',
    age: 24,
  };
})();

特点:

  1. 不加 library,则将所有属性 mixin 到 this 上
  2. 加 library,则将对象挂载到 this[library]字段上

二、libraryTarget: “window”

逻辑同 this,只是将 this 替换成 window

三、libraryTarget: “global”

逻辑同 this,只是将 this 替换成 global(由于 webpack 默认 target 为"web",所以默认即使设置 libraryTarget 为 global,最终的挂载对象仍然是 window。需要先将 target 改为"node",才能使得挂载对象为 global)

四、libraryTarget: “commonjs”

逻辑同 this,只是将 this 替换成 exports

第三类:更符合模块定义系统

一、libraryTarget:“commonjs2”

webpack 配置:

output: {
  ...
  libraryTarget: 'commonjs2',
},

编译后的文件如下所示:

module.exports = (() => {
  return {
    name: 'jack',
    age: 24
  }
})());

加了 library 之后的 webpack 配置:

output: {
  ...
  library: 'finalModule',
  libraryTarget: 'commonjs2',
},

编译后的文件同上

特点:

  1. 符合 commonjs 规范
  2. 加了 library 没有效果

二、libraryTarget:“amd”

webpack 配置:

output: {
  ...
  libraryTarget: 'amd',
},

编译后的文件如下所示:

define(() => {
  return (() => {
    return {
      name: 'jack',
      age: 24,
    };
  })();
});

加了 library 之后的 webpack 配置:

output: {
  ...
  library: 'finalModule',
  libraryTarget: 'amd',
},

编译后的文件如下所示:

define('finalModule', [], () => {
  return (() => {
    return {
      name: 'jack',
      age: 24,
    };
  })();
});

特点:

  1. 符合 amd 规范
  2. 加了 library,会改为定义 library 模块

三、libraryTarget:“umd”

webpack 配置:

output: {
  ...
  libraryTarget: 'umd',
},

编译后的文件如下所示:

(function webpackUniversalModuleDefinition(root, factory) {
  if (typeof exports === 'object' && typeof module === 'object') module.exports = factory();
  else if (typeof define === 'function' && define.amd) define([], factory);
  else {
    var a = factory();
    for (var i in a) (typeof exports === 'object' ? exports : root)[i] = a[i];
  }
})(window, () => {
  return (() => {
    return {
      name: 'jack',
      age: 24,
    };
  })();
});

加了 library 之后的 webpack 配置:

output: {
  ...
  library: 'finalModule',
  libraryTarget: 'umd',
},

编译后的文件如下所示:

(function webpackUniversalModuleDefinition(root, factory) {
  if (typeof exports === 'object' && typeof module === 'object') module.exports = factory();
  else if (typeof define === 'function' && define.amd) define([], factory);
  else if (typeof exports === 'object') exports['finalModule'] = factory();
  else root['finalModule'] = factory();
})(window, () => {
  return (() => {
    return {
      name: 'jack',
      age: 24,
    };
  })();
});

特点:

  1. 定义了兼容各种模块的执行函数
  2. 不加 library,则将所有属性 mixin 到导出模块上
  3. 加 library,则将对象挂载到导出模块的 library 字段上

注意:
同之前的 libraryTarget: "global"一样,需要将 target 改为 node,编译后的 window 才会被改为 global

  • 12
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值