【问题标题】:three.js ES6 how import only specific modules三.js ES6 如何只导入特定模块
【发布时间】:2018-02-10 11:00:41
【问题描述】:

我已经通过 NPM 安装了 three.js 库,以利用新的 ES6 模块化架构,它应该让您只导入所需的模块,如下所述:Threejs - Import via modules

我正在使用gulpbrowserifybabel 进行捆绑和转译,如下所示:

gulp.task("build_js", () => {

return browserify({
    entries: "./public/app/app.js",
    cache: {},
    dev: true
})
    .transform(babelify, {presets: ["env"], plugins: ["syntax-async-functions", "transform-async-to-generator"], sourceMaps: true})
    .bundle()
    .pipe(source("app.bundle.min.js"))
    .pipe(buffer())
    .pipe(sourcemaps.init({loadMaps: mode}))
    .pipe(uglify())
    .pipe(sourcemaps.write("./"))
    .pipe(gulp.dest(config.build.js))

});

我只想导入我需要的模块并保持较小的包大小,但我注意到 browserify 生成的包具有相同的大小,无论我导入所有模块还是只导入一个。

如果我在 app.js 中导入所有模块,我得到的包大小约为 500Kb:

// app.js

import * as THREE from 'three'; // about 500 Kb size

但如果我尝试使用 ES6 语法仅导入特定模块,我会得到相同的包大小(它再次导入所有模块):

// app.js

import { Vector3 } from 'three'; // about 500 Kb size, same as before example

我还尝试了以下方法:

// app.js

import { Vector3 } from "three/build/three.module.js";

但我收到以下错误:

SyntaxError: 'import' and 'export' may only appear at the top level (45590:0) while parsing /Users/revy/proj001/node_modules/three/build/three.module.js

我的问题:我怎样才能正确地只导入我需要的模块并保持包的大小?

【问题讨论】:

  • 如果你尝试import {Vector3} from 'three/src/math/Vector3会发生什么

标签: javascript three.js browserify babeljs es6-modules


【解决方案1】:

您缺少Tree Shaking 的概念。

当您按名称导入模块时,其他模块不会自动从包中删除。捆绑器始终包含代码中的每个模块,并忽略您指定为导入名称的内容。

您未导入的其他未使用的模块被视为死代码,因为它们位于包中,但您的代码不会调用它们。

因此,要从包中删除这些未使用的代码,从而使包更小,您需要一个支持删除死代码的压缩器。

看看这个流行的browserify摇树插件 - 它应该让你开始:

https://github.com/browserify/common-shakeify

【讨论】:

  • 我不明白。当我导入一个模块时,我希望只导入与该模块相关的代码(以及传递依赖路径中该模块所需的模块)。这不是死代码,它是我的应用程序中需要的代码。不应导入不在传递依赖路径中的模块,还是我遗漏了什么?
  • 捆绑器始终包含所有内容,除非您使用摇树工具。您认为仅包含您明确导入的代码的假设是错误的。
  • 我不是这个主题的专家,但这似乎是错误的。如果您import {Vector3} from './path/Vector3只导入了Vector3 而不是其他所有内容?否则怎么可能,导入其余模块的部分是什么?
  • 是因为... from 'three'吗?来自path/wherever/ThreeClass 的` 应该可以工作吗?
  • 是的,我想这是有道理的,from 'three' 导入所有并产生死代码,可以摇树。但是,直接从模块导入,不应该导致死代码吗?
【解决方案2】:

在 browserify 转换中使用 rollupify 解决。它将执行摇树并删除死代码:

gulp.task("build_js", () => {

return browserify({
    entries: "./public/app/app.js",
    cache: {},
    dev: true
})
    .transform(rollupify, {config: {}})    // <---
    .transform(babelify, {presets: ["env"], plugins: ["syntax-async-functions", "transform-async-to-generator"], sourceMaps: true})
    .bundle()
    .pipe(source("app.bundle.min.js"))
    .pipe(buffer())
    .pipe(sourcemaps.init({loadMaps: mode}))
    .pipe(uglify())
    .pipe(sourcemaps.write("./"))
    .pipe(gulp.dest(config.build.js))

});

}

我仍然希望解释一下为什么 ES6 模块导入会这样工作..

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-18
    • 2017-01-04
    • 1970-01-01
    • 2016-05-16
    • 2016-02-12
    相关资源
    最近更新 更多