Как включить скрипты, находящиеся внутри папки node_modules?

У меня есть вопрос относительно наилучшей практики для включения node_modules в веб-сайт HTML.

Представьте, что у меня есть Bootstrap внутри моей папки node_modules. Теперь для дистрибутивной версии сайта (живой версии), как бы я включил скрипт Bootstrap и CSS файлы, расположенные внутри папки node_modules? Есть ли смысл оставлять Bootstrap внутри этой папки и делать что-то вроде следующего?

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

Или мне нужно добавить правила в мой файл gulp, которые затем скопируют эти файлы в мою папку dist? Или лучше было бы позволить gulp каким-то образом полностью удалить локальный загрузчик из моего HTML файла и заменить его версией CDN?

Ответ 1

Обычно вы не хотите раскрывать какие-либо внутренние пути для того, как ваш сервер структурирован по отношению к внешнему миру. Что вы можете сделать, так это создать на вашем сервере статический маршрут /scripts который извлекает его файлы из любого каталога, в котором они находятся. Так что, если ваши файлы находятся в "./node_modules/bootstrap/dist/". Затем тег script на ваших страницах выглядит так:

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

Если вы использовали экспресс с nodejs, статический маршрут так же прост:

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

Затем любые запросы браузера из /scripts/xxx.js будут автоматически выбираться из вашего каталога dist адресу __dirname +/node_modules/bootstrap/dist/xxx.js.

Примечание: более новые версии NPM помещают больше вещей на верхний уровень, не вкладываясь так глубоко, поэтому, если вы используете более новую версию NPM, имена путей будут отличаться от указанных в вопросе OP и в текущем ответе. Но концепция все та же. Вы узнаете, где файлы физически расположены на диске сервера и вы делаете app.use() с 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>

И код для создания маршрута для этого

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

Ответ 2

Я бы использовал модуль npm пути, а затем сделал что-то вроде этого:

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

Ответ 3

Как упомянуто jfriend00, вы не должны раскрывать структуру вашего сервера. Вы можете скопировать файлы зависимостей вашего проекта в нечто вроде public/scripts. Вы можете сделать это очень легко с помощью dep-linker:

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

Ответ 4

Каталог 'node_modules' может не находиться в текущем каталоге, поэтому вы должны разрешить путь динамически.

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

Ответ 5

Если вы хотите быстрое и простое решение (и у вас установлено 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']);

Недостатком этого является то, что он не автоматизирован. Однако, если все, что вам нужно, это скопировать несколько сценариев и стилей (и сохранить их в списке), это должно сработать.

Ответ 6

Я хочу обновить этот вопрос с помощью более простого решения. Создайте символическую ссылку на node_modules.

Самый простой способ предоставить публичный доступ к node_modules - создать символическую ссылку, указывающую на ваш node_modules из вашего общедоступного каталога. Символьная ссылка будет делать так, как если бы файлы существовали везде, где создана ссылка.

Например, если сервер node имеет код для обслуживания статических файлов

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

или как это в окнах:

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 call, например:

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

и в node добавить:

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

Ответ 7

Я не нашел никаких чистых решений (я не хочу раскрывать источник всех моих node_modules), поэтому я просто написал Powershell script, чтобы скопировать их:

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

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

Ответ 8

Я сделал следующие изменения для 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>
<% } %>

Ответ 9

В моем приложении Angular 2 у меня есть это в файле Index.html:

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

Вот полный файл:

<!DOCTYPE html>
<html>
<head>
    <base href="/" />
    <title>TripMate - PPS</title>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="stylesheet" href="styles.css">
    <link rel="stylesheet" href="node_modules/bootstrap/dist/css/bootstrap.min.css" />

    <!-- Polyfill(s) for older browsers -->
    <script src="node_modules/core-js/client/shim.min.js"></script>

    <script src="node_modules/zone.js/dist/zone.js"></script>
    <script src="node_modules/reflect-metadata/Reflect.js"></script>
    <script src="node_modules/systemjs/dist/system.src.js"></script>

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

    <script src="systemjs.config.js"></script>
    <script>
        System.import('app').catch(function(err) { console.error(err); });
    </script>
</head>

  <body>
    <my-app>Loading...</my-app>
  </body>
</html>

Ответ 10

Это то, что я настроил на моем 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>

Удачи...