【问题标题】:NOde.js/Express App can't find some node_modulesNOde.js/Express App 找不到一些 node_modules
【发布时间】:2018-09-19 15:10:00
【问题描述】:

我在我的应用程序中使用了几个 Node/Express 模块,只要我使用 const module = require('module');,每个模块都可以正常工作。我不需要将这些模块的静态路径定义为app.use(express.static(path.join(__dirname, 'public')));

但是,对于 sweetalert 模块,如果我在 layout.pug(基本 pug 文件)script(src="/node_modules/sweetalert/dist/sweetalert.min.js") 中定义,我会收到 404 错误(未找到)除非我在 app.js 中包含以下静态路径:app.use("/node_modules", express.static(__dirname + "/node_modules"));

我的问题是:这是正常行为还是我做得不对? (我有点困惑,为什么我必须为我使用的几个模块之一定义静态路径。

【问题讨论】:

    标签: node.js express path sweetalert


    【解决方案1】:

    这是怎么回事:

    app.use(express.static(path.join(__dirname, 'public'))); 声明浏览器可以访问公共目录。您应该将所有前端资源放在该文件夹中。这将有助于区分可以从服务器访问的内容和可以从客户端访问的内容。

    当您引用 script(src="/node_modules/sweetalert/dist/sweetalert.min.js") 时,浏览器会抛出 404,因为该文件不在公共目录中,因此无法访问浏览器。

    添加这一行app.use("/node_modules", express.static(__dirname + "/node_modules"));“修复”了您的问题,但现在会将您的所有 node_modules 暴露给浏览器。这可能不是一个好主意,我相信安全专家可以详细说明为什么不应该这样做。

    我将如何解决此问题:检查您的 .pug 代码并查看您的前端需要的任何资源。然后将它们复制到公用文件夹并修复您的引用以使用资源的副本。

    这是我用来将资源从 node_module 目录移动到 public/assets 目录的脚本示例:

    build.js:

    const path = require('path');
    var fs = require('fs');
    
    const ASSETS = [
        'jquery/dist/jquery.min.js',
        'sweetalert/dist/sweetalert.min.js'
    ];
    
    if (!fs.existsSync('./public/assets')){
        fs.mkdirSync('./public/assets');
    }
    
    ASSETS.map(asset => {
        let filename = asset.substring(asset.lastIndexOf("/") + 1);
        let from = path.resolve(__dirname, `./node_modules/${asset}`)
        let to = path.resolve(__dirname, `./public/assets/${filename}`)
        if (fs.existsSync(from)) {
            fs.createReadStream(from).pipe(fs.createWriteStream(to));
         } else {
            console.log(`${from} does not exist.\nUpdate the build.js script with the correct file paths.`)
            process.exit(1)
        }
    });
    

    然后我更新我的 package.json 以将其包含在脚本中:

    package.json:

    "scripts": {
        "build": "node ./build.js || true",
        "start": "node ./bin/www"
    }
    

    然后在我的任何视图页面中,我使用新路径引用资源

    random.pug:

    script(src="/assets/jquery.min.js")
    script(src="/assets/sweetalert.min.js")
    

    最后,在部署应用之前,您现在必须运行以下命令: npm run build 然后npm start

    如果您的前端资源发生变化,您只需要运行构建命令。因此,如果您只使用过sweetalert.min.js,您只需在第一次运行应用程序时运行构建。如果稍后您添加另一个资源aNewResource.js,您将需要更新build.js 文件并再次运行npm run build

    【讨论】:

    • 感谢您的回答!要了解所有安全问题和顾虑,我还有很长的路要走。
    • 另外一个问题:在我的页面中,我想提供wav文件供浏览器收听,并询问用户一些相关问题。为了能够访问定义它的 json 文件,我使用相同的“配方”:app.use("/definitions", express.static(__dirname + "/definitions")); app.use("/sounds", express.static(__dirname + "/sounds")); app.use("/answers", express.static(__dirname + "/answers"));。我的问题是:有没有办法在不将所有这些信息暴露给任何好奇的用户的情况下做到这一点?
    • 只需将您计划在浏览器中使用的任何内容移动到公共目录即可。所以创建一个 public/sounds 目录。除非出于某种访问控制原因不向浏览器公开所有文件。
    • 是的,有些内容不暴露是有原因的,应该是盲听实验……否则如果暴露了一些信息,答案就会有偏差
    • 访问控制:假设你有一个文件,你只想向几个用户公开,如果你把它放在公共目录中,任何人都可以通过转到 yourdomain/sounds/fileA.wav 来访问它,以防止你将其放在公共目录之外的其他位置,然后通过路由中的 get 调用访问媒体/
    猜你喜欢
    • 1970-01-01
    • 2014-06-04
    • 2014-11-07
    • 2012-05-22
    • 2020-06-13
    • 2018-12-05
    • 1970-01-01
    • 2016-12-04
    • 2013-02-03
    相关资源
    最近更新 更多