Three.js: Импорт примеров модулей jsm заставляет сборщики пакетов дважды связывать исходный код three.js

Созданный на 12 сент. 2019  ·  43Комментарии  ·  Источник: mrdoob/three.js

При импорте из three/examples/jsm/.../<module> сборщики пакетов (проверенные с помощью накопительного пакета) включают библиотеку дважды (или несколько раз).

Например, при выполнении import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls' сборщик будет следовать за импортом, а в OrbitControls.js импорт поступает из ../../../build/three.module.js . Однако (внешний) сборщик не может знать, что ../../../build/three.module.js - это тот же модуль, что и three .

Решением для этого было бы рассматривать модули примеров как внешние пакеты и импортировать из three вместо ../../../build/three.module.js . Это может нарушить конфигурацию накопительного пакета three.js, но должна быть возможность указать накоплению, что three является псевдонимом для основной точки входа из трех ( src/Three.js ).

Самый полезный комментарий

Думаю, к этому просто нужно привыкнуть. Теперь, когда я думаю, что понял, меня устраивает то, как оно есть.

Кстати, я обновил threejsfundamentals, чтобы все они были основаны на ESM, поэтому 🤞

Все 43 Комментарий

(проверено с помощью накопительного пакета)

Подтвердить с помощью накатки не могу. Если вы делаете это, как в следующей настройке проекта, все работает, как ожидалось.

https://github.com/Mugen87/three-jsm

Если вы рассматриваете three как внешнюю зависимость:

export default {
    input: 'src/main.js',
    external: ['three'],
    output: [
        {
            format: 'umd',
            name: 'LIB',
            file: 'build/main.js'
        }
    ],
    plugins: [ resolve() ]
};

тогда вывод не должен содержать исходный код three.js, но он включает все.

Если, однако, вы не импортируете OrbitControls, то вывод будет включать только исходный код файла main.js .

вы можете попробовать это, закомментировав импорт OrbitControls , а затем построив его снова (но с 'three' качестве внешней зависимости).

Это связано с # 17220 - одно из предложенных решений заключалось в замене поля main в package.json на путь сборки модуля, но это не исправило этот вариант использования.

Чтобы прояснить ситуацию, проблема заключается в том, что, хотя three помечается как внешний для создания отдельного пакета, который зависит от трех в конфигурации накопления, который не улавливает жесткую ссылку на ../../../build/three.module.js и включает его в сборку. Например, создание следующего файла будет непреднамеренно включать код OrbitControls _и_ код threejs в пакет, а также импортировать еще одну копию трех при сборке с опубликованной конфигурацией @adrian-delgado.

// src/main.js
import * as THREE from 'three';
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';

console.log(THREE, OrbitControls);

@ adrian-delgado, возможно, стоит отметить, что даже если путь в OrbitControls.js будет изменен на three OrbitControls все равно будут включены в ваш пакет, что может быть или нежелательно и может привести как минимум к код OrbitControls дважды включается в зависимые приложения.

Я не хочу предлагать это как долгосрочное или лучшее решение, но изменение конфигурации, чтобы пометить OrbitControls (и все файлы в трех папках) как внешние, решит это в обоих случаях:

export default {
    // ...

    external: p => /^three/.test(p),

    // ...
};

Я не хочу предлагать это как долгосрочное или лучшее решение, но изменение конфигурации, чтобы пометить OrbitControls (и все файлы в трех папках) как внешние, решит это в обоих случаях:

По какой-то причине я ожидал, что свертка также по умолчанию будет обрабатывать 'three/examples/jsm/controls/OrbitControls.js' как внешнюю. Итак, ваше предлагаемое решение подходит для моего варианта использования.

Соответствующий № 17220 очень актуален. Наверное, стоит продолжить разговор на этом.

Что произойдет, если вы это сделаете?

// src/main.js
import * as THREE from 'three/build/three.module.js';
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';

console.log(THREE, OrbitControls);

Это сработает, но это невозможно, потому что любая другая библиотека или фрагмент кода, зависящий от трех, будет импортироваться из «трех», а затем снова сломается. Package.json обычно сообщает среде, как разрешить, «build / three.module» - это деталь распределения, которая не должна просачиваться. Когда разрешение пропущено, это просто вызывает проблемы с пространством имен.

  external: p => /^three/.test(p),

@gkjohnson Что делать, если пользователь хочет включить в пакет экземпляр «три» и OrbitControls ?

Не уверен, что это связано, подобное происходит, если вы пытаетесь использовать модули вживую, как это

import * as three from 'https://cdnjs.cloudflare.com/ajax/libs/three.js/108/three.module.js';
import { OrbitControls } from 'https://threejs.org/examples/jsm/controls/OrbitControls.js';

загружает файл three.js дважды, один раз из CDN и еще раз из threejs.org

Возможно, это не тот способ, которым предполагается использовать модули с тремя, но, начиная с версии до 106, есть тысячи сайтов и примеров, которые

<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/105/three.min.js"></script>
<script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>

Все примеры показывают использование модулей в реальном времени вместо сборки (объединения), поэтому в некотором смысле они не показывают фактический способ использования three.js, как раньше. Другими словами, старые примеры работали «из коробки». Новые примеры не похожи. Чтобы пример работал, вам нужно извлечь JavaScript из примера и поместить в отдельный файл .js, а затем поместить three.js локально (возможно, через npm). Исправьте все пути в примерах, чтобы они были путями на основе пакетов (без ../.././build), и, наконец, используйте накопление

Это довольно большое изменение по сравнению с версиями без модуля, для которых достаточно было просто изменить пути.

@mrdoob

С исходной конфигурацией @adrian-delgado три.js будут включены один раз, а элементы управления орбитой будут включены один раз, и никакие пакеты не будут помечены как внешние. С конфигурацией, которую я предложил, будет внешняя зависимость от three/build/three.module.js и three/examples/jsm/controls/OrbitControls.js в созданном пакете.

@EliasHasle

Что, если пользователь хочет включить в пакет «три» экземпляра и OrbitControls?

Затем следует исключить поле external в этом случае в комплект будет включена одна копия из трех элементов управления орбитой. rollup-plugin-node-resolve (который необходим для свертки для поддержки разрешения модуля и используется в приведенных выше конфигурациях) по умолчанию использует поле модуля package.json (см. параметр mainFields ), поэтому орбита контролирует три ссылки, а «три» разрешит один и тот же сценарий. _Если mainFields изменить на ["main", "module"] так что "main" используется вместо "module" в package.json_, то здесь будут включены две копии из трех, и все сломается так, как было раньше. упоминалось ранее. Однако это требует изменения этого поля. Если, однако, используется «main», то, вероятно, также понадобится rollup-plugin-commonjs , потому что rollup не знает, как обрабатывать файлы commonjs, которые по умолчанию используют require.

@greggman

К сожалению, я не думаю, что наивная замена модулей в этом случае сработает так легко. Ни одно из предложенных решений не будет касаться этого случая, и я не думаю, что на данный момент есть что-то официальное, что можно было бы использовать в случае импорта основного скрипта и примера с разных хостов. Насколько мне известно, импорт карт - единственное, над чем мы работаем. Если оба примера и три импортированы с одного и того же хоста, то будет загружена только одна копия из трех:

import * as three from 'https://cdnjs.cloudflare.com/ajax/libs/three.js/108/three.module.js';
import { OrbitControls } from 'https://cdnjs.cloudflare.com/ajax/libs/three.js/108/examples/jsm/controls/OrbitControls.js';

// or

import * as three from 'https://threejs.org/build/three.module.js';
import { OrbitControls } from 'https://threejs.org/examples/jsm/controls/OrbitControls.js';

В зависимости от варианта использования, может быть, предпочтительнее продолжать использовать классические теги сценария?

@greggman

Не уверен, что это связано, подобное происходит, если вы пытаетесь использовать модули вживую, как это

import * as three from 'https://cdnjs.cloudflare.com/ajax/libs/three.js/108/three.module.js';
import { OrbitControls } from 'https://threejs.org/examples/jsm/controls/OrbitControls.js';

Ага ... Не используйте такие модули 😁

Ага ... Не используйте такие модули 😁

Согласовано. Просто возможно, что документы и примеры нацелены в основном на неопытных разработчиков, и тот факт, что примеры jsm используются по умолчанию, и ни один из них не будет работать без компоновщика и не будет работать через какой-либо CDN, является большим изменением.

Раньше вы могли в основном просматривать исходный код на примере, копировать и вставлять в jsfiddle / codepen и т.д., исправлять пути в тегах сценария, и он запускался. Теперь, хотя все примеры не будут работать, если вы не свяжетесь напрямую с сайтом three.js и не будете смотреть, как они ломаются каждый раз, когда версия запускается. (да, я знаю, что существуют немодульные примеры, но они не связаны с https://threejs.org/examples)

@gkjohnson

import * as three from 'https://cdnjs.cloudflare.com/ajax/libs/three.js/108/three.module.js';
import { OrbitControls } from 'https://cdnjs.cloudflare.com/ajax/libs/three.js/108/examples/jsm/controls/OrbitControls.js';

Не работает, OrbitControls не находится в CDN, а пути внутри OrbitContrls ../../../bulild/three.js - неправильный путь для его работы

// или

import * as three from 'https://threejs.org/build/three.module.js';
import { OrbitControls } from 'https://threejs.org/examples/jsm/controls/OrbitControls.js'

Также не работает, так как он будет ломаться каждый раз, когда three.js подталкивает новую версию

Может быть, переместите папку examples / js в CDN и три, чтобы простое исправление URL-адресов в коде примера по-прежнему работало? Это означает, что three.module.js должен быть на

https://cdnjs.cloudflare.com/ajax/libs/three.js/108/build/three.module.js

build добавлено к пути

Чтобы упомянуть варианты, другие CDN, такие как jsdelivr или unpkg, поддерживают модули ES:

Раньше вы могли в основном просматривать исходный код на примере, копировать и вставлять в jsfiddle / codepen и т.д., исправлять пути в тегах script, и он запускался ...

Думаю, нам понадобится импортировать карты, чтобы сделать что-нибудь полезное, к лучшему или к худшему.

Теперь, хотя все примеры не будут работать, если вы не укажете прямую ссылку на сайт three.js

Я бы действительно не стал призывать кого-либо напрямую ссылаться на живые скрипты на сайте threejs ... это никогда не будет хорошей идеей. Согласно приведенному выше комментарию, существуют версионные альтернативы.

Документация, которая в идеале могла бы ответить на эти вопросы, - это страница Импорт через модули . Есть ли дела, которые мы должны там освещать? Думаю, было бы неплохо упомянуть о CDN.

Упоминание CDN было бы хорошей идеей. Также упоминается, что CDN Cloudflare, первое попадание в Google, не подходит для модулей (если это не изменится)

@greggman

Раньше вы могли в основном просматривать исходный код на примере, копировать и вставлять в jsfiddle / codepen и т.д., исправлять пути в тегах сценария, и он запускался.

Я на твоей стороне. Худшая часть модулей заключается в том, что вы больше не можете получить доступ к camera или renderer из консоли в примерах 😟

Как насчет того, чтобы начать использовать unpkg?

Как насчет того, чтобы начать использовать unpkg?

Вы имеете в виду начать использовать его в документации, например на странице « Импорт через модули» , или как-то использовать в проекте?

Худшая часть модулей - это то, что вы больше не можете получить доступ к камере или рендереру с консоли в примерах.

Да, это расстраивает. Я добавлял это (или подобное) в примеры при локальной разработке:

Object.assign( window, { camera, renderer, scene } );

Я предполагаю, что мы надеемся решить эту проблему с помощью расширения инструментов разработчика?

Одна идея, которая потребует некоторого исследования, но может быть интересной ... если бы мы были готовы добавить полифилл карты импорта ко всем примерам, я думаю, мы могли бы сделать используемый импорт на 100% совместимым с npm- и рабочие процессы, основанные на сборщиках. Например:

<script defer src="es-module-shims.js"></script>
<script type="importmap-shim" src="importmap.dev.js"></script>

<!-- ... -->

<script type="module-shim">
  import { Scene, WebGLRenderer } from 'three';
  import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';

  // ...
</script>

Как насчет того, чтобы начать использовать unpkg?

Вы имеете в виду начать использовать его в документации, например на странице «Импорт через модули», или как-то использовать в проекте?

Вместо того, чтобы указывать на https://threejs.org/build/. В настоящее время мы используем эту ссылку в ISSUE_TEMPLATE .

И @greggman, вероятно, мог бы переключиться с https://cdnjs.cloudflare.com/ajax/libs/three.js/108/ на https://unpkg.com/[email protected]/ ?

Похоже, что unpkg решает проблемы, которые мы здесь обсуждаем.

Да, это расстраивает. Я добавлял это (или подобное) в примеры при локальной разработке:

Object.assign( window, { camera, renderer, scene } );

Фу! Ха-ха

Я предполагаю, что мы надеемся решить эту проблему с помощью расширения инструментов разработчика?

Да! 🤞

@greggman

Не уверен, что это связано, подобное происходит, если вы пытаетесь использовать модули вживую, как это

import * as three from 'https://cdnjs.cloudflare.com/ajax/libs/three.js/108/three.module.js';
import { OrbitControls } from 'https://threejs.org/examples/jsm/controls/OrbitControls.js';

Ага ... Не используйте такие модули 😁

Итак, сегодня я обнаружил, что делаю именно это ... 😅 Это действительно плохая привычка, но проблема в том, что большинство вещей работают, но если что-то ломается, довольно сложно закрепить.

В моем случае я импортировал three.module.js из dev и OBJLoader из master . OBJLoader импортировал three.module.js из master поэтому у BufferGeometry не было нового свойства usage , а у WebGLRenderer было не рендерил меш, потому что он не нашел usage , но все остальное сработало 😶

Это довольно волосатая ...

Думаю, к этому просто нужно привыкнуть. Теперь, когда я думаю, что понял, меня устраивает то, как оно есть.

Кстати, я обновил threejsfundamentals, чтобы все они были основаны на ESM, поэтому 🤞

Кажется, что неплохо было бы иметь three.module.min.js (или это three.min.module.js 😜)

+1

Я просто импортирую три элемента управления орбитой в качестве модулей ES6, и поскольку (похоже) элементы управления орбитой относятся к трем в папке сборки, мне потребовалось некоторое время, чтобы выяснить мои пути

Супер фанат, мы можем использовать три в качестве модулей, но было бы неплохо иметь больше гибкости в этом вопросе, я не собираюсь вдаваться в файл управления орбитой и начинать возиться, предполагая, что это также относится и к другим модулям.

Также +1 за three.min.module.js 😎

переход от # 18239, я попал в него подобную проблему, делая npm link на другой пакет, использующий three.js.

Я разработал плагин -минификатор, который может помочь решить эту проблему.

Я столкнулся с той же проблемой. Я пишу компонент React с использованием three.js и импортирую некоторые модули из примеров. После того, как он связан с накопительным пакетом, если я посмотрю на пакет, я могу увидеть, что есть один оператор импорта для трех, а затем код Three.js.

Если я использую этот оператор импорта в своем компоненте: import * as THREE from "three/build/three.module"
все работает правильно, но затем в пакет встраивается Three, чего я не хочу.
Я хотел бы иметь оператор импорта для троих. Если я использую import * as THREE from "three , в комплекте будет три импортированных модуля, но как только я использую один из примеров, в комплект добавляется three.js (= у меня есть один оператор импорта для трех, а затем код из трех), что в конечном итоге приводит к поломке моего кода

@chabb

Я пишу компонент React с использованием three.js и импортирую некоторые модули из примеров. После того, как он связан с накопительным пакетом, если я посмотрю на пакет, я могу увидеть, что есть один оператор импорта для трех, а затем код Three.js.

Опубликованное здесь решение должно решить вашу проблему: https://github.com/mrdoob/three.js/issues/17482#issuecomment -530957570.

Я чувствую, что многие из этих проблем возникают из-за того, что люди не полностью понимают, что происходит с их сборщиком (что понятно), но эти проблемы не уникальны для трех. Однако возможно, что случайный двойной импорт трех ядер просто более заметен, чем с другими библиотеками. Объединение зависимости, которая должна быть внешней, такой как lodash, компонент React или OrbitControls, проще не заметить.

Что касается зависимости от внешнего пакета, Rollup документирует это поведение и предоставляет возможность здесь, а Webpack имеет аналогичный вариант здесь . В этом случае, если бы файлы примеров вместо этого ссылались на «три», тогда, хотя основная библиотека не была бы объединена, вы все равно получите дублирующиеся пакеты кода примера, что является его собственной проблемой. И я не думаю, что этот проект может что-то сделать, чтобы помочь сборщику интерпретировать подводные камни npm-ссылок. Я думаю, что единственный проблемный случай, который я видел, который, как мне кажется, не является результатом неправильно настроенного связующего, - это случай codeandbox.

Для случаев сборщика, возможно, ответ состоит в том, чтобы задокументировать, добавить руководство по устранению неполадок или ссылку на то, как настроить общие сборщики на странице импорта через модули .

У меня есть подозрение, что если examples/jsm пакеты могут изменить этот шаблон ...

// <strong i="7">@file</strong> GLTFLoader.js

// Before
import { Mesh } from '../../build/three.module.js';

// After
import { Mesh } from 'three';

... эти вопросы было бы намного проще решить. К сожалению, я не знаю, как мы будем управлять примерами HTML на веб-сайте threejs без сложной настройки сборки. Полифилл карты импорта на сайте threejs может решить эту проблему, но я не уверен. : /

если бы файлы примеров вместо этого ссылались на «три», тогда, хотя основная библиотека не была бы объединена, вы все равно получили бы дублирующиеся пакеты кода примера ...

Я не совсем понимаю это. Потому что это импорт относительного пути? Мы могли бы сделать их относящимися к пакету.

@donmccurdy

У меня есть подозрение, что если бы пакеты examples / jsm могли изменить этот шаблон ... эти проблемы было бы намного легче решить.

Я думаю, что это будет выглядеть решенным, но у людей все равно будет дублированный код, который будет труднее заметить, потому что это не приведет к поломке приложения.

Я не совсем понимаю это. Потому что это импорт относительного пути? Мы могли бы сделать их относящимися к пакету.

Извините, если мне непонятно, я думаю, что это немного сложно объяснить - надеюсь, это немного яснее. Я воспользуюсь случаем Rollup:

В приведенных выше случаях, когда люди хотят объединить пакет с three помеченным как внешний, я предполагаю, что они создают библиотеку, в которой three.js будет одноранговой зависимостью, на которую может полагаться другое приложение:

import * as THREE from 'three';
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';
import { stuff } from './local/src/index.js';

// library code with exports...

Здесь цель состоит в том, чтобы указанный выше импорт three.js оставался в библиотеке, а пакет - для загрузки трех и OrbitControls в качестве одноранговых зависимостей, поэтому, если приложение также использует three.js и OrbitControls, вы не импортируете их дважды.

Люди ожидают, что опция external: [ 'three' ] обеспечит для них такое поведение (я определенно сделал), но это не так, потому что строка не соответствует пути импорта OrbitControls. Это приводит к тому, что OrbitControls непреднамеренно объединяется и, следовательно, ../../../build/three.module.js объединяется (потому что он также не соответствует строке). Я думаю, что люди указывают на объединенный файл ядра three.js, потому что он гораздо более заметен - приложения ломаются, пакет библиотеки намного больше и т.д. первое место ._ Правильный способ настройки Rollup здесь - установить для параметра значение external: path => /^three/.test( path ) .

Это не уникально для трех. Rollup использует lodash в качестве примера в своих документах, но будет сложно / невозможно заметить, если 'lodash/merge' будет добавлен в код вашей библиотеки, потому что он такой маленький и не вызовет дублирующих ошибок импорта. Пользовательский интерфейс материала поощряет вложенные ссылки на файлы при импорте, и аналогичным образом параметр external: ['@material-ui/core'] не сможет исключить '@material-ui/core/Button' из пакета.

Я не думаю, что стоит менять пример кода для этих вариантов использования, потому что это все равно приведет к дублированию кода, которого не было бы, если бы сборщик был настроен правильно.

Здесь два случая:

(1) пользователь хочет, чтобы три js и примеры были включены один раз, получает что-то дважды

Например, при создании приложения.

(2) пользователь хочет, чтобы три js и примеры включались ноль раз, получает что-то 1+ раз

Например, при создании библиотеки с тремя внешними или одноранговыми зависимостями.


Насколько я знаю, и (1), и (2) по-прежнему остаются легкими проблемами? Если вышеприведенный подход решает (1), это уже полезно. Я не уверен насчет (2). Может быть, стоит упомянуть трюк /^three/.test( path ) при импорте через модули ?

@gkjohnson Спасибо за это объяснение, оно действительно помогло мне прояснить мои мысли

В моей конфигурации накопительного пакета я определил external таким образом

[
        ...Object.keys(pkg.dependencies || {}),
        ...Object.keys(pkg.peerDependencies || {}),
        ...other_stuff
      ]

Я думал, что это сработает, поскольку три будут рассматриваться как внешние зависимости; но, как вы упомянули, вы должны использовать регулярное выражение (насколько я понимаю, я думаю, это потому, что примеры делают
import from "../../../build/three.module.js"; ). Итак, я закончил тем, что сделал

external: p => {
      if ([
        ...Object.keys(pkg.dependencies || {}),
        ...Object.keys(pkg.peerDependencies || {}),
        'prop-types'
      ].indexOf(p) > -1) {
        return true;
      }
      return /^three/.test(p) ;
    }

Это немного не связанный с этим вопрос, но я ожидаю, что все зависимости, которые я объявил в package.json , не являются частью пакета? Это правильное предположение?

@donmccurdy

Насколько я знаю, и (1), и (2) по-прежнему остаются легкими проблемами?

На мой взгляд (2) является результатом неправильной настройки сборщика пакетов, и, возможно, мы сможем решить эту проблему, обновив документацию с некоторыми предложениями для сборщиков. (1) может возникнуть в результате использования пакета, который страдает от проблемы (2), но кроме этого, я не уверен, что (1) легко наткнуться. Я хотел бы увидеть реальный пример использования, который демонстрирует проблему, чтобы увидеть, как кто-то настроил свой сборщик, но вот список способов, которые, как я знаю, вы можете решить (пока):

  1. Явно импортируйте из 'three/src/Three.js' или 'three/build/three.min.js' (что не рекомендуется в документации).
  2. Измените конфигурацию сборщика для использования поля package.main а не поля package.module при разрешении. Однако все три больших сборщика пакетов Rollup , Webpack и Parcel по умолчанию предпочитают module main . Этот вариант использования кажется необычным, но это всего лишь предположение.
  3. Используйте npm link чтобы включить пакет с символической ссылкой, который зависит от трех (это исправляется с помощью параметра preserveSymlinks накопления).
  4. Используйте три и примеры в codeandbox.io, потому что платформа главному полю над модулем .

Номер 4 кажется единственным, на что можно легко наткнуться, хотя я знаю, что люди делают 1 для тряски дерева. Остальные чувствуют, что они находятся вне нашего контроля или могут быть очень необычными.

@chabb

насколько я понимаю, я предполагаю, что это потому, что в примерах выполняется import from "../../../build/three.module.js"; ...

Это не так, пожалуйста, прочтите то, что я объяснил здесь: https://github.com/mrdoob/three.js/issues/17482#issuecomment -583694493. /^three работает, потому что соответствует строке 'three/examples/jsm/controls/OrbitControls.js' которая также должна быть внешней, поскольку она является частью библиотеки three.js, а строка 'three' - нет. То же самое может случиться и с другими зависимостями. Я бы рекомендовал использовать регулярное выражение для всех зависимостей, чтобы избежать других неизвестных ловушек или сопоставить с любым пакетом с голым спецификатором модуля.

@gkjohnson Спасибо за подробное объяснение, которое имеет для меня смысл.

Похоже, это все-таки не решает проблему в этой ветке, но, поскольку я уже упоминал об этом пару раз в ветке, я наконец протестировал полифил карты импорта: https://github.com/KhronosGroup/ Программное обеспечение KTX / pull / 172 / files. С этим полифилом import * as THREE from 'three'; работает в веб-браузере.

Если бы только браузер показал некоторую уверенность ...
https://github.com/WICG/import-maps/issues/212#issuecomment -663564421

Я столкнулся с той же проблемой при добавлении подкласса прохода в один из моих проектов.

import { /* stuff */ } from 'three'
import { Pass } from 'three/examples/jsm/postprocessing/Pass.js'

И поскольку я предпочел скопировать код Pass в свой модуль, чтобы не импортировать его позже из three.js в браузере, я нашел обходной путь:

const threeModulePath = path.resolve( __dirname, 'node_modules/three/build/three.module.js' );

export default {
    /* ..... */
    external: [ 'three' ],
    output: [
        {
            /* .... */
            globals : {
                'three': 'THREE',
                [ threeModulePath ]: 'THREE',
            }
        }
    ]
};

Таким образом, он работает с браузерами, и импорт модулей также должен работать.

Редактировать :

Загрузка из трех локальных проектов (см. Пример ниже) нарушит этот подход и потребует дополнительного обходного пути.

"dependencies" : {
    "three": "file:../three.js"
}

Что ж, я пошел дальше и сделал новую версию, которая поддерживает локальную ссылку:

const threeName = "three"; // Change with your three package name
const dependencies = require('./package.json').dependencies;
const splits = dependencies[threeName].split('file:');

const modulePath = (splits.length > 1) ?
    path.resolve(__dirname, splits[1], 'build/three.module.js'):                  // Resolve local path
    path.resolve(__dirname, 'node_modules', threeName, 'build/three.module.js');  // Resolve node_module path

const external = [
    threeName,
    modulePath,
]

const globals = {
    [threeName]: 'THREE',
    [modulePath]: 'THREE',
}

@Mcgode Это было рассмотрено выше в https://github.com/mrdoob/three.js/issues/17482#issuecomment -530957570. Если вы используете Rollup и хотите пометить three.js как внешние при использовании примеров модулей, вам необходимо сделать следующее, как предлагается:

externals: p => /^three/.test(p),

Нет причин усложнять конфигурацию. Это гарантирует, что и файл Pass.js, и модуль three.js будут помечены как externel.

@gkjohnson Мой three lib, а не пример (я хочу, чтобы пример был связан с моей сборкой).

Я создаю библиотеку с тремя в качестве внешней, я хочу, чтобы пример был объединен по ширине сборки, но без трех, и, как обсуждалось выше, при импорте модуля из примеров вывод будет содержать код трех. Можно ли добиться с помощью webpack?

import {  } from "three";
import { Line2 } from "three/examples/jsm/lines/Line2";
import { LineGeometry } from "three/examples/jsm/lines/LineGeometry";

@Mcgode @recardinal Я не думаю, что это возможно. Я хотел сделать то же самое, поэтому просто скопировал / вставил код из примеров; в моем случае мне пришлось «отрегулировать» импорт и экспорт, и все. Очевидно, это не идеально, но для моего случая этого было достаточно.

У меня здесь аналогичный вариант использования с Webpack и THREE в качестве внешнего. Следующий импорт приводит к включению файла three.module.js в объединенный вывод.

import * as THREE from 'three';
import { ColladaLoader } from 'three/examples/jsm/loaders/ColladaLoader';
import { OBJLoader } from 'three/examples/jsm/loaders/OBJLoader';
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader';

Я где-то читал, что примеры / js / * в какой-то момент будут удалены. Было бы неплохо, если бы примеры jsm до этого «просто работали».

Была ли эта страница полезной?
0 / 5 - 0 рейтинги

Смежные вопросы

seep picture seep  ·  3Комментарии

fuzihaofzh picture fuzihaofzh  ·  3Комментарии

ghost picture ghost  ·  3Комментарии

clawconduce picture clawconduce  ·  3Комментарии

jack-jun picture jack-jun  ·  3Комментарии