如何在下一个 js 中从节点模块外部的文件夹中导入模块

Posted

技术标签:

【中文标题】如何在下一个 js 中从节点模块外部的文件夹中导入模块【英文标题】:How to import modules from a folder outside node modules in next js 【发布时间】:2020-02-28 07:56:13 【问题描述】:

我一直在努力从 three.js 导入示例模块,我在我的项目中使用了 next.js(服务器端反应框架),并在 express 中使用了自定义服务器。我的服务器代码看起来像这样 -

const express = require('express');
const next = require('next');

const favicon = require('serve-favicon');
var path = require('path');
let fs = require('fs')

const dev = process.env.NODE_ENV !== 'production';
const nextApp = next( dev );

nextApp.prepare()
    .then(() => 

        let server = express(), options = , PORT = 3000, app = express()

        if (dev) 
            // DEVELOPMENT ///

            // DEVELOPMENT ///  
        
        else 
            // PRODUCTION ///

            options = 
                ...options
            
            // PRODUCTION ///
        

        server.use(favicon(path.join(__dirname, "/favicon.ico")))


        server.get('/', (req, res) => 
            const actualPage = '/';
            nextApp.render(req, res, actualPage);
        );

        server.get('*', (req, res) => 
            const actualPage = '/not-found';

            nextApp.render(req, res, actualPage);
            // return handle(req, res)
        );


        server.listen((PORT), (err) => 
            if (err) throw err
            console.log('>> Ready on ' + PORT)
        )

    )

    .catch((ex) => 
        console.error(ex.stack)
        process.exit(1)
    )

我基本上运行了一个 npx create-next-app 并在我的 next.js 项目中配置了一个 custom express server 用于动态路由,如您在上面的代码中所见。

然后,我使用 three.js 在我的 App.js 文件中导入和渲染的 home 组件中创建了一个场景。我的 home.js 组件看起来像这样 -

import React,  useState, useEffect  from 'react'
import * as THREE from 'three'
import  TrackballControls  from 'three/examples/jsm/controls/TrackballControls'

import "../src/assets/sass/home.scss"

const X = () => 

let parent, renderer, scene, camera, TrackballControls

useEffect(() => 

    // renderer
    renderer = new THREE.WebGLRenderer()
    renderer.setSize( window.innerWidth, window.innerHeight )
    document.body.appendChild( renderer.domElement )

    // scene
    scene = new THREE.Scene()

    // camera
    camera = new THREE.PerspectiveCamera( 40, window.innerWidth / window.innerHeight, 1, 100 )
    camera.position.set( 20, 20, 20 )

    // controls
    controls = new TrackballControls( camera )
    controls.minDistance = 5
    controls.maxDistance = 250
    controls.enableDamping = true; // an animation loop is required when either damping or auto-rotation are enabled
    controls.dampingFactor = 0.05;

    // axes
    // scene.add(new THREE.AxisHelper( 20 ))

    // geometry
    let geometry = new THREE.SphereGeometry( 2, 8, 6, 0, 6.3, 0, 3.1)

    // material
    let material = new THREE.MeshBasicMaterial(
        wireframe: true,
        wireframeLinewidth: 1
    )

    let sphere = new THREE.Mesh( geometry, material )

    // parent
    parent = new THREE.Object3D()
    scene.add( parent )
    scene.add( sphere )

    function animate() 
        requestAnimationFrame( animate )
        parent.rotation.z += 0.01
        controls.update()
        renderer.render( scene, camera )
    

    animate()


,[])

return <div></div>


export default X

现在这是我面临的问题 - 我正在从名为 TrackballControls 的三个.js 中导入一个示例模块,它并不完全位于核心三模块内,而是在它外部的文件夹中可以从路径中看到 - 'three/examples/jsm/controls/TrackballControls.js'。你可以在这里看到更多 - Importing es6 modules separately。但不知何故,它不起作用。它抛出了一个类似

的错误

我尝试使用简单的 create-react-app 做同样的事情,导入完全有效!所以我知道我的服务器端代码有问题,我假设这是一个与 webpack 相关的问题。但我对 webpack 真的一无所知。有人请帮助我,我们将不胜感激!

如果有帮助,这是我的 next.config.js 文件 -

const withSASS = require('@zeit/next-sass')

const  parsed: localEnv  = require('dotenv').config()
const webpack = require('webpack')
// const path = require('path')

function HACK_removeMinimizeOptionFromCssLoaders(config) 
  console.warn(
    'HACK: Removing `minimize` option from `css-loader` entries in Webpack config',
  )
  config.module.rules.forEach(rule => 
      if (Array.isArray(rule.use)) 
          rule.use.forEach(u => 
      if (u.loader === 'css-loader' && u.options) 
          delete u.options.minimize
    
  )

)


module.exports = withSASS(
  
      webpack(config) 
        HACK_removeMinimizeOptionFromCssLoaders(config)
        config.plugins.push(new webpack.EnvironmentPlugin(localEnv))

        return config
  
  )

【问题讨论】:

我尝试了您的方法来包含github.com/tradingview/lightweight-charts,但进展不顺利,如果时间允许,您能否发布一个带有轻量级图表的示例。除了上述要求,感谢您发布您的发现。它有助于理解我所面临的问题。 【参考方案1】:

我知道这里没有人看到这个,但如果将来有人遇到这个问题,我会发布我的解决方案。所以这就是我想出来的-

我没有在我的问题中提到我使用的是名为 next.js 的 s-s-r(服务器端渲染)反应框架。导入与纯反应应用程序完美配合。但是在服务器端框架中,与导入相关的东西应该在 useEffect(或 componentDidMount)中完成,以及其余的 threejs 东西。所以我像这样动态导入它-

let dynamicallyImportPackage = async () => 
let TrackballControls

await import('three/examples/jsm/controls/TrackballControls')
// you can now use the package in here
.then(module => 
    TrackballControls = module.TrackballControls
)
.catch(e => console.log(e))

return TrackballControls

然后,我像这样在我的 useEffect 中使用它 -

let TrackbackControls = await dynamicallyImportPackage()

// controls
controls = new TrackbackControls(camera, container)
controls.minDistance = 5
controls.maxDistance = 250

Arigato Gosaimasu!

【讨论】:

以上是关于如何在下一个 js 中从节点模块外部的文件夹中导入模块的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Ionic 3 中导入外部 JS 文件

在 Storybook Vue 中导入节点模块

如何使用 npm 在 ES6 中导入 moment.js?

在 Angular 2 应用程序中导入节点 js 模块

如何在打字稿项目中导入节点模块。 ERR_REQUIRE_ESM

如何在 Vue 组件中导入外部函数?