我有一个关于将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版本?


当前回答

如果你要链接很多文件,创建一个白名单,然后使用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/ bootstrap .js, /npm/bootstrap/ bootstrap .css等等。

顺便说一句,我很想知道是否有一种方法可以使用express.static来加入白名单

其他回答

正如jfriend00提到的,你不应该公开你的服务器结构。您可以将项目依赖文件复制到公共/脚本之类的文件中。你可以用dep-linker很容易做到这一点,像这样:

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

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

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

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

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

如果你要链接很多文件,创建一个白名单,然后使用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/ bootstrap .js, /npm/bootstrap/ bootstrap .css等等。

顺便说一句,我很想知道是否有一种方法可以使用express.static来加入白名单

我做了下面的更改,以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>
<% } %>