繁体   English   中英

BabelJS 和 Webpack 配置以获得最大可能的兼容性

[英]BabelJS and Webpack config for maximum possible compatibility

我的网站必须使用可以想象到的最基本的手机浏览器,因为我的用户群是埃塞俄比亚农村儿童,他们使用非常非常基本的手机。 (我正在使用 jquery 来节省手机电池,因为大多数都是“回收的”,二手/三/四手和古老的,而且我非常小心数据成本。)

我正在尝试设置 Babel + Webpack 以转换为尽可能低的可支持目标,但我误解了 Babel 文档,(例如,我从@babel/preset-env开始并且没有目标,因为我认为不定位意味着最大兼容性,但这不是 polyfill),并且无法针对我的大量目标手机和浏览器进行测试。

  • 下面的配置是否会生成并捆绑 Javascript 将在最大可能的浏览器范围内运行? 有什么办法让它更兼容吗?

  • 我有useBuiltins=usage - 下面的 webpack 配置会检测到重复导入和树抖动吗? 如果不是我需要更改什么,或者我的index.js中的useBuiltins=entryrequire('core-js');require('regenerator-runtime/runtime')会更好吗?

  • 使用importrequire来导入 bootstrap 会生成比 bootstrap 发行版更大的文件,即使我在 JS 中没有引用它。 我怎样才能让摇树工作? 我不应该通过 npm 使用 jquery 吗? 编辑:摇树只发生在 PROD 构建上,并且似乎正在使用以下配置。

  • 我可以安全地使用最新的 jquery 并依赖 polyfill,而不是 1.12,它存在安全问题,但我正在使用它,因为它适用于更多浏览器?

  • 我可以删除@babel/cli ,因为 webpack 正在运行 babel 吗? (它有效,我只是想确保我得到了每一盎司的 polyfill 和兼容性,如果更好的话,我很乐意运行 babel CLI。)

  • 还有其他错过的机会/建议吗?

(If relevant, I do not need any chunking - this is a simple app and I am caching indefinitely. I am writing this into a Django static folder, and Django + whitenoise are handling filename fingerprinting and HTTP compression. I will at some point add JS 单元测试。我正在为 polyfills 和 tree-shaking 导入 bootstrap JS(尽管 Bootstrap 似乎没有在摇晃),但是直接从 HTML 加载 bootstrap CSS 以避免在我更新应用程序时缓存未命中。)

packages.json

{
  ...
  "scripts": {
    "start": "webpack-dev-server --open --mode development",
    "build": "webpack --mode production",
  },
  "devDependencies": {
    "@babel/cli": "^7.10.1",
    "@babel/core": "^7.10.2",
    "@babel/plugin-proposal-class-properties": "^7.10.1",
    "@babel/preset-env": "^7.10.2",
    "axios": "^0.19.2",
    "babel-loader": "^8.1.0",
    "bootstrap": "^4.4.1",
    "jquery": "^1.12.4",  // insecure old version but more compatible
    "popper.js": "^1.16.1",
    "webpack": "^4.43.0",
    "webpack-cli": "^3.3.11",
    "webpack-dev-server": "^3.11.0"
  },
  "dependencies": {
    "@babel/polyfill": "^7.10.1",
    "core-js": "^3.6.5"
  }
}

.babelrc

{
  "presets": [
    [
      "@babel/env",
      {
        "targets": "cover 100%",
        "useBuiltIns": "usage",
        "corejs": "3.6.5"
      }
    ]
  ],
  "plugins": ["@babel/plugin-proposal-class-properties"]
}

webpack.config.js

const path = require('path');

module.exports = {
  module: {
    rules: [
      {
        test: /\.(js|jsx)$/,
        exclude: /node_modules/,
        use: {
          loader: "babel-loader"
        }
      }
    ]
  },
  output: {
    filename: 'app.js',
    publicPath: "/static/",
    path: path.join(__dirname, '../djangoproj/app/static/app')
  },
  devServer: {
    writeToDisk: true, // Django serves the content
  }
};

index.js

import $ from 'jquery';
import bootstrap from 'bootstrap'
import popper from 'popper.js'
import {Controller} from './controller';

$(document).ready(function() {
  const app = new Controller()
})

controller.js

import {View} from './view';
import {ActivityStore, ElementStore} from './store';
import {Api} from './api';

export class Controller {
  constructor() {
    this.state = {}
    this.api = new Api(config)

// and so on..

更新:我决定不按照@tfr 的建议逐步填充(使用<script type="module".. ),因为对我来说测试最低手机比优化新手机更重要。 如果我在更现代的测试设备上运行 polyfill,这种情况更有可能发生。 也就是说,core-js 声称只有在必要时才使用 polyfill,所以我不确定nomodules是否真的会在包大小之外产生影响(我对这项技术的大部分理解是选择我相信我理解的更多信息) . 我还决定直接从浏览器加载 Bootstrap 和 Popper,而不是捆绑。 我正在考虑生成一个vendor.js ,但不确定是否有任何优势,除了它们可能会在我的包中的 polyfill 之前加载。

非常感谢。

通常最好的方法是同时捆绑双重(现代浏览器和旧版),因此您不必填充现代设备。 看看这个工作 polyfill 示例

这就是你如何为现代浏览器加载 es6 和为旧版浏览器加载 es5 包的方式:

  <!-- main bundle -->
  <script type="module" src="/assets/scripts/main.js"></script>
  <!-- polyfilled legacy browser -->
  <script nomodule src="/assets/scripts/main.legacy.js" defer="defer"></script>

这里是您问题的主要答案:

Babel Config
============

const legacy = {
  presets: [
    ["@babel/preset-env", {
      targets: {
        browsers: [
          "> 1% in ET", // make sure its the right country code
          "ie >= 6",
          "not dead"
        ]
      },
      useBuiltIns: "usage",
      corejs: 3,
    }]
  ],
  plugins: [
    "@babel/plugin-syntax-dynamic-import",
    "transform-eval"
  ],
  comments: false,
  cacheDirectory: path.join(CACHE_PATH, 'babel-loader')
};


Webpack Config
==============

 const prod = {
  module: {
    rules: [
      {
        enforce: 'pre',
        test: /\.js$/,
        exclude: [
          /node_modules/
        ],
        use: {
          loader: 'eslint-loader',
        },
      },
      {
        test: /\.js$/,
        exclude: [
          /node_modules/
        ],
        loader: "babel-loader",
        options: babelConfig
      }
    ]
  },
  resolve: {
    extensions: ['.js', '.json'],
  }
};

snippets from https://github.com/unic/darvin-webpack-boilerplate/blob/master/webpack/settings/javascript-legacy/index.js

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM