如何包含位于node_modules文件夹中的脚本?

时间:2014-12-13 22:12:10

标签: node.js twitter-bootstrap npm node-modules

我有一个关于将node_modules加入HTML网站的最佳做法的问题。

想象一下,我的node_modules文件夹中有Bootstrap。现在,对于网站的分发版本(实时版本),我如何在node_modules文件夹中包含Bootstrap脚本和CSS文件?将Bootstrap放在该文件夹中并执行以下操作是否有意义?

<script src="./node_modules/bootstrap/dist/bootstrap.min.js></script>

或者我是否必须将规则添加到我的gulp文件中,然后将这些文件复制到我的dist文件夹中?或者最好让gulp以某种方式从我的HTML文件中完全删除本地引导程序并将其替换为CDN版本?

11 个答案:

答案 0 :(得分:259)

通常,您不希望公开任何内部路径,以了解服务器如何构建到外部世界。您可以在服务器中创建一个/scripts静态路由,从其所在的目录中获取文件。因此,如果您的文件位于"./node_modules/bootstrap/dist/"。然后,页面中的脚本标记如下所示:

<script src="/scripts/bootstrap.min.js"></script>

如果你使用带有nodejs的express,静态路由就像这样简单:

app.use('/scripts', express.static(__dirname + '/node_modules/bootstrap/dist/'));

然后,来自/scripts/xxx.js的所有浏览器请求都会自动从dist的{​​{1}}目录中提取。

注意:较新版本的NPM会将更多内容放在顶层,而不是嵌套得如此之深,因此如果您使用较新版本的NPM,则路径名称将与OP的问题和当前答案中指示的不同。但是,这个概念仍然是一样的。您可以找到文件在服务器驱动器上的物理位置,并使用__dirname + /node_modules/bootstrap/dist/xxx.js app.use()来创建这些文件的伪路径,这样您就不会将实际的服务器文件系统组织暴露给客户。


如果您不想制作这样的静态路由,那么您最好将公共脚本复制到Web服务器视为express.static()的路径或任何顶级名称想用。通常,您可以将此复制作为构建/部署过程的一部分。


如果您只想在目录中公开一个特定文件,而不是在该目录中找到所有文件,那么您可以手动为每个文件创建单独的路径,而不是使用/scripts,例如:

express.static()

为此创建路径的代码

<script src="/bootstrap.min.js"></script>

或者,如果您仍希望使用app.get('/bootstrap.min.js', function(req, res) { res.sendFile(__dirname + '/node_modules/bootstrap/dist/bootstrap.min.js'); }); 描述脚本的路线,则可以执行以下操作:

/scripts

为此创建路径的代码

<script src="/scripts/bootstrap.min.js"></script>

答案 1 :(得分:17)

我会使用路径npm模块,然后执行以下操作:

var path = require('path');
app.use('/scripts', express.static(path.join(__dirname, 'node_modules/bootstrap/dist')));

答案 2 :(得分:8)

如jfriend00所述,您不应暴露您的服务器结构。您可以将项目依赖项文件复制到public/scripts之类的内容。您可以使用dep-linker这样非常轻松地执行此操作:

var DepLinker = require('dep-linker');
DepLinker.copyDependenciesTo('./public/scripts')
// Done

答案 3 :(得分:6)

目录&#39; node_modules&#39;可能不在当前目录中,因此您应该动态地解析路径。

var bootstrap_dir = require.resolve('bootstrap')
                           .match(/.*\/node_modules\/[^/]+\//)[0];
app.use('/scripts', express.static(bootstrap_dir + 'dist/'));

答案 4 :(得分:4)

如果您想要快速简便的解决方案(并且已经安装了gulp)。

在我的gulpfile.js我运行一个简单的复制粘贴任务,将我可能需要的任何文件放入./public/modules/目录。

gulp.task('modules', function() {
    sources = [
      './node_modules/prismjs/prism.js',
      './node_modules/prismjs/themes/prism-dark.css',
    ]
    gulp.src( sources ).pipe(gulp.dest('./public/modules/'));
});

gulp.task('copy-modules', ['modules']);

这方面的缺点是它没有自动化。但是,如果您只需要复制一些脚本和样式(并保存在列表中),那么这应该可以胜任。

答案 5 :(得分:3)

我想用更简单的解决方案更新此问题。创建一个指向node_modules的符号链接。

授予对node_modules的公共访问权限的最简单方法是在公共目录中创建指向node_modules的符号链接。符号链接将使文件存在于创建链接的任何位置。

例如,如果节点服务器具有用于提供静态文件的代码

app.use(serveStatic(path.join(__dirname, 'dist')));

和__dirname引用/ path / to / app,以便从/ path / to / app / dist

提供静态文件

并且node_modules位于/ path / to / app / node_modules,然后在mac / linux上创建这样的符号链接:

ln -s /path/to/app/node_modules /path/to/app/dist/node_modules

或在Windows上喜欢这样:

mklink /path/to/app/node_modules /path/to/app/dist/node_modules

现在获取请求:

node_modules/some/path 

将收到

文件的回复
/path/to/app/dist/node_modules/some/path 

这是

中的文件
/path/to/app/node_modules/some/path

如果/ path / to / app / dist中的目录不是一个安全的位置,可能是因为来自构建过程与gulp或grunt的干扰,那么您可以为该链接添加一个单独的目录并添加一个新的serveStatic调用如:

ln -s /path/to/app/node_modules /path/to/app/newDirectoryName/node_modules

并在节点中添加:

app.use(serveStatic(path.join(__dirname, 'newDirectoryName')));

答案 6 :(得分:3)

我没有找到任何干净的解决方案(我不想公开所有node_modules的来源)所以我只是写了一个Powershell脚本来复制它们:

$deps = "leaflet", "leaflet-search", "material-components-web"

foreach ($dep in $deps) {
    Copy-Item "node_modules/$dep/dist" "static/$dep" -Recurse
}

答案 7 :(得分:1)

我对AUTO-INCLUDE索引html中的文件进行了以下更改。因此,当您在文件夹中添加文件时,它将自动从文件夹中获取,而无需您在index.html中包含该文件

//// THIS WORKS FOR ME 
///// in app.js or server.js

var app = express();

app.use("/", express.static(__dirname));
var fs = require("fs"),

function getFiles (dir, files_){
    files_ = files_ || [];
    var files = fs.readdirSync(dir);
    for (var i in files){
        var name = dir + '/' + files[i];
        if (fs.statSync(name).isDirectory()){
            getFiles(name, files_);
        } else {
            files_.push(name);
        }
    }
    return files_;
}
//// send the files in js folder as variable/array 
ejs = require('ejs');

res.render('index', {
    'something':'something'...........
    jsfiles: jsfiles,
});

///--------------------------------------------------

///////// in views/index.ejs --- the below code will list the files in index.ejs

<% for(var i=0; i < jsfiles.length; i++) { %>
   <script src="<%= jsfiles[i] %>"></script>
<% } %>

答案 8 :(得分:0)

这是我在express服务器上设置的内容:

// app.js
const path = require('path');
const express = require('express');
const expressApp  = express();
const nm_dependencies = ['bootstrap', 'jquery', 'popper.js']; // keep adding required node_modules to this array.
nm_dependencies.forEach(dep => {
  expressApp.use(`/${dep}`, express.static(path.resolve(`node_modules/${dep}`)));
});

<!-- somewhere inside head tag -->
<link rel="stylesheet" href="bootstrap/dist/css/bootstrap.css" />

<!-- somewhere near ending body tag -->
<script src="jquery/dist/jquery.js" charset="utf-8"></script>
<script src="popper.js/dist/popper.js" charset="utf-8"></script>
<script src="bootstrap/dist/js/bootstrap.js" charset="utf-8"></script>

祝你好运...

答案 9 :(得分:0)

要在html中使用来自node_modules的多个文件,我发现的最好方法是将它们放入数组,然后在它们上循环以使它们对于Web客户端可见,例如,使用来自node_modules的filepond模块:

const filePondModules = ['filepond-plugin-file-encode', 'filepond-plugin-image-preview', 'filepond-plugin-image-resize', 'filepond']
filePondModules.forEach(currentModule => {
    let module_dir = require.resolve(currentModule)
                           .match(/.*\/node_modules\/[^/]+\//)[0];
    app.use('/' + currentModule, express.static(module_dir + 'dist/'));
})

然后在html(或布局)文件中,像这样调用它们:

    <link rel="stylesheet" href="/filepond/filepond.css">
    <link rel="stylesheet" href="/filepond-plugin-image-preview/filepond-plugin-image-preview.css">
...
    <script src="/filepond-plugin-image-preview/filepond-plugin-image-preview.js" ></script>
    <script src="/filepond-plugin-file-encode/filepond-plugin-file-encode.js"></script>
    <script src="/filepond-plugin-image-resize/filepond-plugin-image-resize.js"></script>
    <script src="/filepond/filepond.js"></script>

答案 10 :(得分:0)

如果您要链接到许多文件,请创建一个白名单,然后使用 sendFile():

app.get('/npm/:pkg/:file', (req, res) => {
    const ok = ['jquery','bootstrap','interactjs'];
    if (!ok.includes(req.params.pkg)) res.status(503).send("Not Permitted.");
    res.sendFile(__dirname + `/node_modules/${req.params.pkg}/dist/${req.params.file}`);
    });

例如,您可以安全地链接到 /npm/bootstrap/bootsrap.js、/npm/bootstrap/bootsrap.css 等。

顺便说一句,我很想知道是否有办法使用 express.static 将其列入白名单