Three.js: La importación de módulos jsm de ejemplos hace que los paquetes agrupen el código fuente de three.js dos veces

Creado en 12 sept. 2019  ·  43Comentarios  ·  Fuente: mrdoob/three.js

Importar desde three/examples/jsm/.../<module> hace que los paquetes (probados con el resumen) incluyan la biblioteca dos veces (o varias veces).

Por ejemplo, al hacer import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls' , el empaquetador seguirá la importación y en OrbitControls.js las importaciones provienen de ../../../build/three.module.js . Sin embargo, no hay forma de que el empaquetador (externo) sepa que ../../../build/three.module.js es el mismo módulo que three .

Una solución para esto sería tratar los módulos de ejemplos como paquetes externos e importarlos desde three lugar de ../../../build/three.module.js . Esto podría romper la configuración de resumen de three.js, pero debería ser posible decirle a rollup que three es un alias para el punto de entrada principal de tres ( src/Three.js ).

Comentario más útil

Creo que es algo a lo que hay que acostumbrarse. Ahora que creo que lo entiendo, estoy bien con la forma en que está.

Por cierto, actualicé tresjsfundamentals para que todos estén basados ​​en esm, así que 🤞

Todos 43 comentarios

(probado con rollup)

No puedo confirmar esto con el resumen. Si lo está haciendo como en la siguiente configuración del proyecto, todo funciona como se esperaba.

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

Si trata three como dependencia externa:

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

entonces la salida no debe contener el código fuente de three.js, pero lo incluye todo.

Sin embargo, si no importa OrbitControls, la salida solo incluirá el código fuente del archivo main.js .

puede probarlo comentando la importación de OrbitControls y luego compilando nuevamente (pero con 'three' como dependencia externa).

Esto está relacionado con # 17220: una de las soluciones propuestas allí era reemplazar el campo main en package.json con la ruta de construcción del módulo, pero eso no solucionaría este caso de uso.

Solo para que quede claro, el problema aquí es que mientras three se marca como externo para construir un paquete separado que depende de tres en la configuración acumulada que no capta la referencia estricta a ../../../build/three.module.js y lo incluye en la compilación. Por ejemplo, la construcción del siguiente archivo incluirá inadvertidamente el código de OrbitControls _y_ el código de threejs en el paquete, así como también importará otra copia de tres cuando se construya con la configuración publicada de @ 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, podría valer la pena señalar que incluso si la ruta en OrbitControls.js se cambia a three OrbitControls todavía se incluirán en su paquete, lo que puede o no ser deseado y podría resultar en al menos el código OrbitControls se incluye dos veces en aplicaciones dependientes.

No pretendo proponer esto como una solución a largo plazo o la mejor, pero cambiar la configuración para marcar OrbitControls (y todos los archivos en la carpeta tres) como externos resolvería esto en ambos casos:

export default {
    // ...

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

    // ...
};

No pretendo proponer esto como una solución a largo plazo o la mejor solución, pero cambiar la configuración para marcar OrbitControls (y todos los archivos en la carpeta tres) como externos resolvería esto en ambos casos:

Por alguna razón, esperaba que el resumen tratara 'three/examples/jsm/controls/OrbitControls.js' como externo también de forma predeterminada. Entonces, su solución propuesta es buena para mi caso de uso.

El # 17220 relacionado es muy relevante. Probablemente la conversación debería continuar allí.

Entonces, ¿qué pasa si haces esto?

// 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);

Funcionaría, pero no es factible, porque cualquier otra lib o pieza de código que dependa de tres se importará desde "tres" y luego se romperá nuevamente. Package.json normalmente le dice al entorno cómo resolver, "build / three.module" es un detalle de distribución que no debería filtrarse. Cuando se omite la resolución, eso solo invita a problemas de espacio de nombres.

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

@gkjohnson ¿Qué OrbitControls en el paquete?

No estoy seguro de que esté relacionado, sucede algo similar si intenta usar módulos en vivo como este

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';

carga three.js dos veces, una desde CDN y nuevamente desde threejs.org

Tal vez esa no es la forma en que se supone que se deben usar los módulos con tres, pero solo desde la versión anterior a 106 hay miles de sitios y ejemplos que sí lo hacen.

<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>

Todos los ejemplos muestran el uso de módulos en vivo en lugar de compilar (agrupar), por lo que, en cierto sentido, no muestran la forma real de usar three.js como solían hacerlo. En otras palabras, los viejos ejemplos funcionaron fuera de la caja. Los nuevos ejemplos no AFAIK. Para que un ejemplo funcione, debe extraer el JavaScript del ejemplo y colocarlo en un archivo .js separado, luego colocar tres.js localmente (probablemente a través de npm). Corrija todas las rutas en los ejemplos para que sean rutas basadas en paquetes (no ../.././build), y finalmente use rollup

Ese es un cambio bastante grande con respecto a las versiones sin módulo para las que solo cambiar las rutas fue suficiente

@mrdoob

Con la configuración original de @ adrian-delgado, three.js se incluirán una vez y los controles de órbita se incluirán una vez y ningún paquete se marcará como externo. Con la configuración que propuse, habrá una dependencia externa en three/build/three.module.js y three/examples/jsm/controls/OrbitControls.js en el paquete producido.

@EliasHasle

¿Qué sucede si el usuario desea incluir la instancia "tres" y OrbitControls en el paquete?

Luego, el campo external debe excluirse, en cuyo caso se incluirá una sola copia de tres controles de órbita en el paquete. rollup-plugin-node-resolve (que se necesita para que el resumen admita la resolución del módulo y se está utilizando en las configuraciones anteriores) utiliza de forma predeterminada el campo del módulo de package.json (consulte la opción mainFields ) por lo que la órbita controla tres referencias y "tres" se resolverán en el mismo script. _Si mainFields se cambia a ["main", "module"] por lo que se usa "main" en lugar de "module" en package.json_, entonces se incluirán aquí dos copias de tres y las cosas se romperán de la manera que se ha hecho. previamente mencionado. Sin embargo, requiere cambiar ese campo. Sin embargo, si se utiliza "main", es probable que también se necesite rollup-plugin-commonjs , porque rollup no sabe cómo procesar los archivos commonjs que utilizan require de forma predeterminada.

@greggman

Desafortunadamente, no creo que un reemplazo ingenuo de módulos funcione tan fácilmente en este caso. Ninguna de las soluciones propuestas abordará este caso y no creo que haya nada oficial en este momento que pueda usarse para ayudar en el caso de importar el script principal y el ejemplo desde hosts separados. Los mapas de importación son lo único que se está trabajando para ayudar con esto, hasta donde yo sé. Si tanto el ejemplo como tres se importan desde el mismo host, solo se cargará una única copia de tres:

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';

Dependiendo del caso de uso, ¿quizás sea preferible continuar usando las etiquetas de script clásicas?

@greggman

No estoy seguro de que esté relacionado, sucede algo similar si intenta usar módulos en vivo como este

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';

Sí ... No uses módulos como ese 😁

Sí ... No uses módulos como ese 😁

Acordado. Podría decirse que los documentos y ejemplos están dirigidos principalmente a desarrolladores sin experiencia y el hecho de que los ejemplos de jsm son los predeterminados y ninguno de ellos funcionará sin un constructor ni funcionará a través de ningún CDN es una especie de gran cambio.

Solía ​​ser que básicamente podía ver la fuente en un ejemplo, copiar y pegar en jsfiddle / codepen, etc., arreglar las rutas en las etiquetas del script y se ejecutaría. Ahora, aunque todos los ejemplos no se ejecutarán a menos que se vincule directamente al sitio three.js y observe cómo se rompen cada vez que se cambia la versión. (sí, sé que existen ejemplos que no son de módulo, pero esos no son los vinculados desde 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';

No funciona, OrbitControls no está en el CDN y las rutas dentro de OrbitContrls ../../../bulild/three.js no es la ruta correcta para que funcione

// o

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

Tampoco funciona, ya que se romperá cada vez que three.js inserte una nueva versión

¿Tal vez empujar la carpeta examples / js a un CDN y tres de modo que simplemente arreglar las URL en el código de ejemplo seguirá funcionando? Eso significa que three.module.js debe estar en

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

build agregado a la ruta

Solía ​​ser que básicamente podía ver la fuente en un ejemplo, copiar y pegar en jsfiddle / codepen, etc., arreglar las rutas en las etiquetas del script y se ejecutaría ...

Creo que necesitaremos importar mapas para hacer algo útil al respecto, para bien o para mal.

Ahora, aunque todos los ejemplos no se ejecutarán a menos que se vincule directamente al sitio three.js

Realmente no recomendaría a nadie que vincule directamente a los scripts en vivo en el sitio de threejs ... eso nunca será una buena idea. Hay alternativas versionadas, según el comentario anterior.

La documentación que, idealmente, respondería a estas preguntas es la página Importar a través de módulos . ¿Hay casos que deberíamos cubrir allí? Supongo que mencionar las CDN sería una buena idea.

Sería una buena idea mencionar las CDN. También se menciona que el Cloudflare CDN, el primer éxito, en Google no es bueno para los módulos (a menos que eso cambie)

@greggman

Solía ​​ser que básicamente podía ver la fuente en un ejemplo, copiar y pegar en jsfiddle / codepen, etc., arreglar las rutas en las etiquetas del script y se ejecutaría.

Estoy de tu lado. La peor parte de los módulos es que ya no puede acceder a camera o renderer desde la consola en los ejemplos 😟

¿Qué tal si empezamos a usar unkg?

¿Te refieres a comenzar a usarlo en documentación como la página Importar a través de módulos , o usarlo en el proyecto de alguna manera?

La peor parte de los módulos es que ya no puede acceder a la cámara o al renderizador desde la consola en los ejemplos.

Sí, eso es frustrante. He estado lanzando esto (o similar) en los ejemplos al desarrollar localmente:

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

Supongo que eso es algo que esperamos resolver con una extensión de herramientas de desarrollo.

Una idea que requeriría algo de investigación, pero podría ser interesante ... si estuviéramos dispuestos a agregar un polyfill de mapa de importación a todos los ejemplos, creo que podríamos hacer que las importaciones utilizadas allí sean 100% compatibles con copiar / pegar con npm- y flujos de trabajo basados ​​en paquetes. Por ejemplo:

<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>

¿Qué tal si empezamos a usar unkg?

¿Te refieres a comenzar a usarlo en documentación como la página Importar a través de módulos, o usarlo en el proyecto de alguna manera?

En lugar de apuntar a https://threejs.org/build/. Actualmente estamos usando ese enlace en ISSUE_TEMPLATE .

¿Y @greggman probablemente podría cambiar de https://cdnjs.cloudflare.com/ajax/libs/three.js/108/ a https://unpkg.com/[email protected]/ ?

Parece que unkg resuelve los problemas que estamos discutiendo aquí.

Sí, eso es frustrante. He estado lanzando esto (o similar) en los ejemplos al desarrollar localmente:

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

¡Puaj! Ja ja

Supongo que eso es algo que esperamos resolver con una extensión de herramientas de desarrollo.

¡Sí! 🤞

@greggman

No estoy seguro de que esté relacionado, sucede algo similar si intenta usar módulos en vivo como este

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';

Sí ... No uses módulos como ese 😁

Así que hoy me encontré haciendo precisamente eso ... 😅 Es un mal hábito, pero el problema es que la mayoría de las cosas funcionan, pero si algo se rompe es bastante difícil de precisar.

En mi caso, estaba importando three.module.js de dev y OBJLoader de master . OBJLoader importó three.module.js de master por lo que BufferGeometry no tenía la nueva propiedad usage , y WebGLRenderer sí no renderizar la malla porque no encontró usage , aunque todo lo demás funcionó 😶

Esto es bastante peludo ...

Creo que es algo a lo que hay que acostumbrarse. Ahora que creo que lo entiendo, estoy bien con la forma en que está.

Por cierto, actualicé tresjsfundamentals para que todos estén basados ​​en esm, así que 🤞

Sin embargo, parece que podría ser bueno tener un three.module.min.js (o es que three.min.module.js 😜)

+1

Solo estoy importando tres controles de órbita como módulos ES6 y porque (parece) los controles de órbita se refieren a tres dentro de la carpeta de compilación, me tomó un tiempo averiguar mis rutas

Súper fan podemos usar tres como módulos, pero sería bueno tener más flexibilidad al respecto, no voy a entrar en el archivo de controles de órbita y comenzar a jugar, asumiendo que este también es el caso con otros módulos.

También +1 para un módulo de tres.min.module.js 😎

pasando de # 18239, me quede atrapado en ella un problema similar al hacer npm link en otro paquete que utiliza three.js.

He desarrollado un complemento de tres minificadores que puede ayudar a resolver este problema.

Estoy enfrentando el mismo problema. Estoy escribiendo un componente de React usando three.js y estoy importando algunos módulos de los ejemplos. Una vez que está incluido con el paquete acumulativo, si miro el paquete, puedo ver que hay una declaración de importación para tres, y luego el código Three.js.

Si utilizo esta declaración de importación en mi componente: import * as THREE from "three/build/three.module"
las cosas funcionan correctamente, pero Three se integra en el paquete, que es algo que no quiero.
Me gustaría tener una declaración de importación para tres. Si uso import * as THREE from "three , el paquete tendrá tres importados como módulo, pero tan pronto como use uno de los ejemplos, se agregará three.js en el paquete (= tengo una declaración de importación para tres, y luego el código de tres), lo que finalmente hace que mi código se rompa

@chabb

Estoy escribiendo un componente de React usando three.js y estoy importando algunos módulos de los ejemplos. Una vez que está incluido con el paquete acumulativo, si miro el paquete, puedo ver que hay una declaración de importación para tres, y luego el código Three.js.

La solución publicada aquí debería resolver su problema: https://github.com/mrdoob/three.js/issues/17482#issuecomment -530957570.

Siento que muchos de estos problemas se derivan de que las personas no comprenden completamente lo que está sucediendo con su paquete (lo cual es comprensible), pero estos problemas no son exclusivos de tres. Sin embargo, es posible que la importación doble accidental de tres núcleos sea más notable que con otras bibliotecas. La combinación de una dependencia que está destinada a ser externa como lodash, un componente de reacción u OrbitControls puede pasarse por alto más fácilmente.

Con respecto a la dependencia de un paquete externo, Rollup documenta este comportamiento y proporciona una opción aquí y Webpack tiene una opción similar aquí . En este caso, si los archivos de ejemplo se referían a "tres", mientras que la biblioteca central no estaría empaquetada, aún obtendría paquetes duplicados de código de ejemplo, que es su propio problema. Y no creo que haya nada que este proyecto pueda hacer para ayudar a un agrupador a interpretar las trampas del enlace npm. Creo que el único caso problemático que he visto y que siento que no es el resultado de un paquete mal configurado es el caso de codesandbox.

Para los casos de empaquetadores, tal vez la respuesta sea documentar, agregar una guía de solución de problemas o un enlace a cómo configurar los empaquetadores comunes en la página de importación a través de módulos .

Tengo el presentimiento de que si los paquetes examples/jsm pudieran cambiar este patrón ...

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

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

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

... estos problemas serían mucho más fáciles de resolver. Desafortunadamente, no sé cómo administraríamos los ejemplos HTML dentro del sitio web threejs sin una configuración de compilación compleja. Un polyfill de mapa de importación en el sitio web de threejs podría resolverlo, pero no estoy seguro. : /

si los archivos de ejemplo se referían a "tres", mientras que la biblioteca central no se incluiría, aún obtendría paquetes duplicados de código de ejemplo ...

No sigo esto del todo. ¿Porque son importaciones de rutas relativas? Podríamos hacerlos relativos al paquete.

@donmccurdy

Tengo el presentimiento de que si los paquetes examples / jsm pudieran cambiar este patrón ... estos problemas serían mucho más fáciles de resolver.

Creo que esto haría que parezca resuelto, pero la gente todavía tendría un código duplicado que es más difícil de notar porque no hace que la aplicación se rompa.

No sigo esto del todo. ¿Porque son importaciones de rutas relativas? Podríamos hacerlos relativos al paquete.

Lo siento si no tengo claro, creo que esto es un poco difícil de explicar; con suerte, esto es un poco más claro. Usaré el caso Rollup:

En los casos anteriores en los que la gente quiere acumular un paquete con three marcado como externo, supongo que están construyendo una biblioteca donde three.js sería una dependencia de pares en la que otra aplicación podría confiar:

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...

Aquí, el objetivo sería que las importaciones de three.js anteriores permanezcan en la biblioteca y el paquete cargue tres y OrbitControls como dependencias de pares, por lo que si la aplicación también usa three.js y OrbitControls, tampoco importa dos veces.

La gente espera que la opción external: [ 'three' ] logre este comportamiento para ellos (ciertamente lo hice) pero no es así porque la cadena no coincide con la ruta de importación de OrbitControls. Esto da como resultado que OrbitControls se empaqueten involuntariamente y, por lo tanto, ../../../build/three.module.js se empaqueten (porque tampoco coincide con la cadena). Creo que la gente señala que el archivo principal three.js está empaquetado porque es mucho más notable: las aplicaciones se rompen, el paquete de la biblioteca es mucho más grande, etc., donde la realidad es que _el archivo OrbitControls no debería haberse empaquetado en el primer lugar._ La forma correcta de configurar Rollup aquí es establecer la opción en external: path => /^three/.test( path ) .

Esto no es exclusivo de tres. Rollup usa lodash como ejemplo en sus documentos, pero será difícil / imposible darse cuenta si 'lodash/merge' se incluye en el código de su biblioteca porque es muy pequeño y no causará errores de importación duplicados. La interfaz de usuario de material fomenta las referencias de archivos anidados en las importaciones y, del mismo modo, la configuración external: ['@material-ui/core'] no excluiría '@material-ui/core/Button' del paquete.

No creo que valga la pena cambiar el código de ejemplo para estos casos de uso porque aún resultará en un código duplicado que no estaría allí si el paquete estuviera configurado correctamente.

Dos casos aquí:

(1) el usuario quiere tresjs y los ejemplos se incluyen una vez, obtiene algo dos veces

Por ejemplo, al crear una aplicación.

(2) el usuario quiere tresjs y los ejemplos se incluyen cero veces, obtiene algo 1+ veces

Por ejemplo, mientras se construye una biblioteca con tres como dependencia externa o entre pares.


Hasta donde yo sé, tanto (1) como (2) siguen siendo problemas fáciles con los que tropezar? Si el enfoque anterior resuelve (1), eso solo es útil. No estoy seguro de (2). ¿Quizás el truco /^three/.test( path ) debería mencionarse al importar a través de módulos ?

@gkjohnson Gracias por esta explicación, realmente me ayudó a aclarar mis pensamientos

En mi configuración de resumen, estaba definiendo el external esta manera

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

Pensé que funcionaría, ya que tres se tratarían como dependencias externas; pero como mencionaste, debes usar una expresión regular (por lo que tengo entendido, supongo que es porque los ejemplos están haciendo
import from "../../../build/three.module.js"; ). Así que terminé haciendo

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

Es una pregunta un poco no relacionada, pero esperaría que todas las dependencias que he declarado en package.json no formen parte del paquete. ¿Es una suposición correcta?

@donmccurdy

Hasta donde yo sé, tanto (1) como (2) siguen siendo problemas fáciles con los que tropezar?

En mi opinión (2) es el resultado de configurar incorrectamente el paquete y tal vez podamos solucionarlo actualizando los documentos con algunas sugerencias para los paquetes. (1) puede ocurrir como resultado del uso de un paquete que tiene el problema (2) pero aparte de eso, no estoy convencido de que (1) sea fácil de encontrar. Me gustaría ver un caso de uso del mundo real que demuestre el problema para ver cómo alguien configuró su agrupador, pero aquí hay una lista de las formas en que sé que puede llegar a esto (hasta ahora):

  1. Importe explícitamente desde 'three/src/Three.js' , o 'three/build/three.min.js' (que no se recomienda en los documentos).
  2. Reconfigure su agrupador para usar el campo package.main lugar del campo package.module al resolver. Sin embargo , los tres grandes paquetes Rollup , Webpack y Parcel prefieren module sobre main de forma predeterminada. Este caso de uso parece poco común, pero eso es solo una suposición.
  3. Use npm link para incluir un paquete de enlace simbólico que dependa de tres (esto se soluciona usando la opción preserveSymlinks paquete acumulativo)
  4. Use tres y ejemplos en codesandbox.io porque la plataforma prioriza el campo principal sobre el módulo .

El número 4 parece ser el único con el que se puede tropezar fácilmente, aunque sé que la gente está haciendo 1 para sacudir árboles. Los demás sienten que están fuera de nuestro control o que serían muy poco comunes.

@chabb

por lo que tengo entendido, supongo que es porque los ejemplos están haciendo import from "../../../build/three.module.js"; ...

Este no es el caso, lea lo que he explicado aquí: https://github.com/mrdoob/three.js/issues/17482#issuecomment -583694493. /^three funciona porque coincide con la cadena 'three/examples/jsm/controls/OrbitControls.js' que también debería ser externa porque es parte de la biblioteca three.js mientras que la cadena 'three' no. Lo mismo puede suceder también con otras dependencias. Recomendaría usar expresiones regulares para todas las dependencias para evitar otras trampas desconocidas o hacer coincidir con cualquier paquete con un especificador de módulo simple.

@gkjohnson Gracias por la explicación detallada, que tiene sentido para mí.

Parece que esto no resuelve el problema en este hilo después de todo, pero como ya lo mencioné un par de veces en el hilo, finalmente probé un polyfill de mapa de importación: https://github.com/KhronosGroup/ KTX-Software / pull / 172 / archivos. Con ese polyfill, import * as THREE from 'three'; funciona en el navegador web.

Si tan solo el navegador mostrara algo de confianza ...
https://github.com/WICG/import-maps/issues/212#issuecomment -663564421

Me encontré con el mismo problema al agregar una subclase de paso a uno de mis proyectos

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

Y como preferí copiar el código de acceso en mi módulo, para no tener que importarlo más tarde desde three.js en el navegador, seguí adelante y encontré una solución alternativa:

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

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

De esta manera, funciona con navegadores y las importaciones de módulos también deberían funcionar.

Editar :

La carga desde un proyecto local de tres (ver ejemplo a continuación) romperá este enfoque y requerirá alguna solución adicional.

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

Bueno, seguí adelante e hice una nueva versión que admite el enlace local:

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 Esto se ha abordado anteriormente en https://github.com/mrdoob/three.js/issues/17482#issuecomment -530957570. Si está utilizando Rollup y le gustaría marcar three.js como externo al usar módulos de ejemplo, debe hacer lo siguiente como se sugiere:

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

No hay razón para hacer la configuración tan complicada. Esto asegurará que tanto el archivo Pass.js como el módulo three.js estén marcados como externos.

@gkjohnson Mi caso de uso no es exactamente el mismo, ya que solo quiero que three lib se marque como externo, no el ejemplo (quiero que el ejemplo se incluya en mi compilación).

Estoy construyendo una biblioteca con tres como externa, quiero que el ejemplo se agrupe a lo ancho de la compilación pero sin tres, y como se discutió anteriormente, cuando se importe el módulo de los ejemplos, la salida contendrá el código de tres. ¿Es posible lograrlo con webpack?

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

@Mcgode @recardinal No creo que sea posible. Quería hacer lo mismo, así que simplemente copié / pegué el código de los ejemplos; en mi caso tuve que 'ajustar' las importaciones y exportaciones y eso fue todo. Obviamente, esto no es ideal, pero fue lo suficientemente bueno para mi caso de uso.

Tengo un caso de uso similar aquí con Webpack y THREE como externo. Las siguientes importaciones hacen que tres.module.js se incluyan en la salida empaquetada.

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';

Leí en alguna parte que los ejemplos / js / * se eliminarán en algún momento. Sería bueno si los ejemplos de jsm "simplemente funcionaran" antes de esa fecha.

¿Fue útil esta página
0 / 5 - 0 calificaciones

Temas relacionados

Bandit picture Bandit  ·  3Comentarios

Horray picture Horray  ·  3Comentarios

jlaquinte picture jlaquinte  ·  3Comentarios

clawconduce picture clawconduce  ·  3Comentarios

filharvey picture filharvey  ·  3Comentarios