「Tips」关于webpack的一些问题

707 阅读4分钟

前言

关于webpack的一些问题的tips

疑问:在使用webpack打包js库时,webpack的配置和babel的配置冲突时js到底会打包成什么模块?

// webpack的配置,打包目标是umd模块
output: {
    path: resolve(__dirname, '../dist'),
    filename: '[name].js',
    library: 'library',
    libraryTarget: 'umd',
 }

// babel的配置
[
  "@babel/preset-env",
  {
    modules: 'cjs'
  }
]   

我经过测试,如果使用webpack打包会无视@babel/preset-env的modules配置。会打包成umd模块

疑问:webpack支持将代码打包成es6的lib吗?

因为之前都是写一些应用程序的代码,没有注意过这些问题。后来谷歌了一下,结果如下👇。

webpack4以及之前都不能将代码打包成es6模块,这是相关的issues。如果想将代码打包成es6模块,可以使用gulp与babel配合。


// 使用gulp和babel打包es6模块的示例
// 直接使用babel将代码编译成es6模块
// gulp配置
const buildEs = () => {
  return src(入口地址)
    .pipe(babel(babelrc()))
    .pipe(dest(输入地址));
};

// babel配置
[
   "@babel/preset-env",
    {
       // 设置为false,将打包成es模块
       modules: false
   }
],

不过webpack将会在下一个版本实现打包成es6模块的功能, 👇

image.png

疑问:webpack通常都会将我们的打包成es5然后配合polyfills使用。但是现在主流浏览器都已经支持es的语法了,我们如何直接使用es的语法?

这是一篇相关的文章:

philipwalton.com/articles/de…

疑问: 如何使用nomodule以及module优化包的大小

这是一个使用了webpack-module-nomodule-plugin,实现nomodule的例子

这是一些相关的文章:

使用nomodule和module优化大小,可以在现代浏览器上减小一半的js大小

疑问: @babel/preset-env的useBuiltIns配置项的含义

useBuiltIns的配置分为3个选项false(不使用垫片),entry,usage

entry

设置entry时,需要在代码的入口文件处手动引入"core-js"和"regenerator-runtime/runtime", 根据不同环境(browsers声明的需要兼容的浏览器,如果是只需要支持最新的浏览器将不会进行转换),babel会将core-js转换不同的内容。

// 入口文件
// 输入
import "core-js";
import "regenerator-runtime/runtime"
// 转换后
import "core-js/modules/es.string.pad-start";
import "core-js/modules/es.string.pad-end";

如果我们明确知道,我们需要那些垫片,可以只引入一部分

// 入口文件
import 'core-js/stable/object/assign'
import 'core-js/features/promise';

usage

在每一个文件使用到垫片时,都会自动进行导入垫片的操作

// a文件
var a = new Promise();
// b文件
var b = new Map();

// a文件转换后
import "core-js/modules/es.promise";
var a = new Promise();
// b文件转换后
import "core-js/modules/es.map";
var b = new Map();

疑问: @babel/runtime和babel/plugin-transform-runtime的关系

  • @babel/plugin-transform-runtime, 作为开发时的依赖。用来转换代码。
  • @babel/runtime,作为生产时的依赖。转换后的代码需要依赖运行时本身所以,所以需要将@babel/runtime作为生产的依赖(需要添加到dependencies)。

还需注意的是transform-runtime的核心版本是可选的,不同的核心转换的API的范围是不同的

  • corejs: false,
  • corejs: 2, 会对全局Promise变量,或者静态属性Array.from做替换。
  • corejs: 3, 除了全局之外,也会对实例属性比如includes做替换。

当我们更改了transform-runtime的corejs的配置,相对应的runtime运行时的版本也需要修改

  • corejs: false,对应@babel/runtime
  • corejs: 2, 对应@babel/runtime-corejs2
  • corejs: 3, 对应@babel/runtime-corejs3

疑问: @babel/preset-env的useBuiltIns: usage和@babel/runtime如何选择?或者说目前那一种才是最佳的实践?

大家可以看下这篇文档, 关键内容如下👇,@babel/runtime无法针对特定的环境,@babel/runtime可能会注入不必要的polyfill内容。

在corejs: 3的设置下,应该是useBuiltIns:usage生成的包是最小的。

Currently, we can't set the target environment as @babel/runtime like we can do for @babel/preset-env. That means that @babel/runtime injects all possible polyfills even when targeting modern engines: it unnecessarily increases the size of the final bundle.

Since core-js-compat contains all the necessary data, in the future, it will be possible to add support for compiling for a target environment to @babel/runtime and to add a useBuiltIns: runtime option to @babel/preset-env.

参考