热搜:fiddler git ip ios 代理
历史搜索

发布、传输和安装现代 JavaScript 以实现更快的应用程序

游客2024-10-12 07:53:01
目录文章目录
  1. 现代 JavaScript
  2. 传统 JavaScript
  3. npm 上的现代 JavaScript
  4. 仅现代
  5. 具有传统回退的现代代码
  6. 具有传统回退的现代代码和 ESM 捆绑程序优化
  7. 应用程序中的现代 JavaScript
  8. webpack
  9. Optimize Plugin
  10. BabelEsmPlugin
  11. 将 babel-loader 配置为转换 node_modules
  12. Rollup
  13. 其他构建工具

发布、传输和安装现代 JavaScript 以实现更快的应用程序 1

BabelEsmPlugin

BabelEsmPlugin 是一个 webpack 插件,它与 @babel/preset-env 一起工作来生成现有捆绑包的现代版本,以将更少的转换代码传输到现代浏览器。它是 Next.js 和 Preact CLI 使用最多的模块/无模块现成解决方案。

// webpack.config.js
const BabelEsmPlugin = require('babel-esm-plugin');

module.exports = {
  //...
  module: {
    rules: [
      // your existing babel-loader configuration:
      {
        test: /.js$/,
        exclude: /node_modules/,
        use: {
          loader: 'babel-loader',
          options: {
            presets: ['@babel/preset-env'],
          },
        },
      },
    ],
  },
  plugins: [new BabelEsmPlugin()],
};

BabelEsmPlugin 支持多种 webpack 配置,因为它运行应用程序的两个基本独立的版本。对于大型应用程序,编译两次可能需要一点额外的时间,但是这种技术允许 BabelEsmPlugin 无缝集成到现有 webpack 配置中,使其成为最方便的选择之一。

将 babel-loader 配置为转换 node_modules

如果使用 babel-loader 而没有使用前两个插件之一,则需要执行一个重要的步骤才能使用现代 JavaScript npm 模块。定义两个单独的 babel-loader 配置可以将 node_modules 中的现代语言特性自动编译为 ES2017,同时仍然使用 Babel 插件和项目配置中定义的预设来转换您自己的第一方代码。这不会为模块/无模块设置生成现代和传统捆绑包,但可以安装和使用包含现代 JavaScript 的 npm 软件包,而不会破坏旧版浏览器体验。

webpack-plugin-modern-npm 使用这种技术来编译在 package.json 中具有 "exports" 字段的 npm 依赖项,因为它们可能包含现代语法:

// webpack.config.js
const ModernNpmPlugin = require('webpack-plugin-modern-npm');

module.exports = {
  plugins: [
    // auto-transpile modern stuff found in node_modules
    new ModernNpmPlugin(),
  ],
};

或者,可以通过在解析模块时检查 package.json 中是否存在 "exports" 字段,在 webpack 配置中手动实现该技术。为简洁起见而省略缓存,自定义实现可能如下所示:

// webpack.config.js
module.exports = {
  module: {
    rules: [
      // Transpile for your own first-party code:
      {
        test: /.js$/i,
        loader: 'babel-loader',
        exclude: /node_modules/,
      },
      // Transpile modern dependencies:
      {
        test: /.js$/i,
        include(file) {
          let dir = file.match(/^.*[/\]node_modules[/\](@.*?[/\])?.*?[/\]/);
          try {
            return dir && !!require(dir[0] + 'package.json').exports;
          } catch (e) {}
        },
        use: {
          loader: 'babel-loader',
          options: {
            babelrc: false,
            configFile: false,
            presets: ['@babel/preset-env'],
          },
        },
      },
    ],
  },
};

使用此方法时,您需要确保缩小器支持现代语法。Terser 和 uglify-es 都有指定 {ecma: 2017} 的选项,以便在压缩和格式化期间保留 ES2017 语法并在某些情况下生成该语法。

Rollup

Rollup 内部支持生成多组捆绑包作为单个版本的一部分,并默认生成现代代码。因此,可以将 Rollup 配置为通过您可能已经在使用的官方插件生成现代和传统捆绑包。

@rollup/plugin-babel

如果使用 Rollup,getBabelOutputPlugin() 方法(由 Rollup 的官方 Babel 插件提供)会转换生成的捆绑包中的代码,而不是单个源模块。Rollup 内部支持生成多组捆绑包作为单个版本的一部分,每个捆绑包都有自己的插件。您可以通过不同的 Babel 输出插件配置来传递各个捆绑包,从而生成不同的现代和传统捆绑包:

// rollup.config.js
import {getBabelOutputPlugin} from '@rollup/plugin-babel';

export default {
  input: 'src/index.js',
  output: [
    // modern bundles:
    {
      format: 'es',
      plugins: [
        getBabelOutputPlugin({
          presets: [
            [
              '@babel/preset-env',
              {
                targets: {esmodules: true},
                bugfixes: true,
                loose: true,
              },
            ],
          ],
        }),
      ],
    },
    // legacy (ES5) bundles:
    {
      format: 'amd',
      entryFileNames: '[name].legacy.js',
      chunkFileNames: '[name]-[hash].legacy.js',
      plugins: [
        getBabelOutputPlugin({
          presets: ['@babel/preset-env'],
        }),
      ],
    },
  ],
};

其他构建工具

Rollup 和 webpack 是高度可配置的,这通常意味着每个项目都必须更新其配置以在依赖项中启用现代 JavaScript 语法。还有更高级的构建工具更倾向于惯例和默认值,而不是配置,例如 Parcel、Snowpack、Vite 和 WMR。这些工具中的大多数假定 npm 依赖项可能包含现代语法,并在生产编译时将它们转换为适当的语法级别。

除了 webpack 和 Rollup 的专用插件,还可以使用 devolution 将具有传统回退的现代 JavaScript 捆绑包添加到任何项目中。Devolution 是一个独立的工具,可转换编译系统的输出以生成传统 JavaScript 变体,从而允许捆绑和转换采用现代输出目标。

原文链接:点击这里