我有一个关于将node_modules包含到HTML网站的最佳实践的问题。

假设我在node_modules文件夹中有Bootstrap。现在对于网站的生产版本,我将如何包括位于node_modules文件夹内的引导脚本和CSS文件?将Bootstrap留在该文件夹中并执行如下操作是否有意义?

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

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


当前回答

通常,您不希望向外部世界公开任何关于服务器结构的内部路径。你所能做的就是在服务器中创建一个/scripts静态路由,从文件所在的目录中获取文件。如果你的文件在"。/node_modules/bootstrap/dist/"目录下。然后,页面中的script标签看起来就像这样:

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

如果你在nodejs中使用express,静态路由就像这样简单:

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

然后,任何来自/scripts/xxx.js的浏览器请求都会自动从dist目录__dirname + /node_modules/bootstrap/dist/xxx.js中获取。

Note: Newer versions of NPM put more things at the top level, not nested so deep so if you are using a newer version of NPM, then the path names will be different than indicated in the OP's question and in the current answer. But, the concept is still the same. You find out where the files are physically located on your server drive and you make an app.use() with express.static() to make a pseudo-path to those files so you aren't exposing the actual server file system organization to the client.


如果你不想创建这样的静态路由,那么你最好将公共脚本复制到你的web服务器将其视为/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>

还有为它创建路径的代码

app.get('/scripts/bootstrap.min.js', function(req, res) {
    res.sendFile(__dirname + '/node_modules/bootstrap/dist/bootstrap.min.js');
});

其他回答

通常,您不希望向外部世界公开任何关于服务器结构的内部路径。你所能做的就是在服务器中创建一个/scripts静态路由,从文件所在的目录中获取文件。如果你的文件在"。/node_modules/bootstrap/dist/"目录下。然后,页面中的script标签看起来就像这样:

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

如果你在nodejs中使用express,静态路由就像这样简单:

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

然后,任何来自/scripts/xxx.js的浏览器请求都会自动从dist目录__dirname + /node_modules/bootstrap/dist/xxx.js中获取。

Note: Newer versions of NPM put more things at the top level, not nested so deep so if you are using a newer version of NPM, then the path names will be different than indicated in the OP's question and in the current answer. But, the concept is still the same. You find out where the files are physically located on your server drive and you make an app.use() with express.static() to make a pseudo-path to those files so you aren't exposing the actual server file system organization to the client.


如果你不想创建这样的静态路由,那么你最好将公共脚本复制到你的web服务器将其视为/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>

还有为它创建路径的代码

app.get('/scripts/bootstrap.min.js', function(req, res) {
    res.sendFile(__dirname + '/node_modules/bootstrap/dist/bootstrap.min.js');
});

如果你想要一个快速简单的解决方案(并且你已经安装了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']);

这样做的缺点是它不是自动化的。然而,如果你所需要的只是复制一些脚本和样式(并保存在一个列表中),这应该可以完成工作。

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

这是我在我的快速服务器上设置的:

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

祝你好运…

我会使用path npm模块,然后做这样的事情:

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

重点:我们使用路径。使用系统不可知的方式使路径连接,即在Windows和Unix中,我们有不同的路径分隔符(/和\)