Как включить скрипты, находящиеся внутри папки 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>
Удачи...