Node_modules klasöründe bulunan komut dosyaları nasıl eklenir?


275

node_modulesBir HTML web sitesine dahil etmek için en iyi uygulama ile ilgili bir sorum var .

node_modulesKlasörümde Bootstrap olduğunu hayal edin . Web sitesinin üretim sürümü için, node_modulesklasörün içindeki Bootstrap komut dosyasını ve CSS dosyalarını nasıl eklerim ? Bootstrap'ı bu klasörün içinde bırakmak ve aşağıdakine benzer bir şey yapmak mantıklı mı?

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

Yoksa daha sonra bu dosyaları dist klasörüne kopyalayan gulp dosyama kurallar eklemek zorunda mıyım? Yoksa gulp'ın bir şekilde yerel bootstrap'i HTML dosyamdan tamamen kaldırmasına ve CDN sürümüyle değiştirmesine izin vermek en iyisi olur mu?


2
ilgili konu stackoverflow.com/questions/24397379/… . Tek bir ihtiyaç olduğunu varsayarsak, bu tek amaç için bower'ın uygulanmasını haklı çıkarıyor mu? Bu, bu tek amaç için şimdi desteğe ihtiyaç duyulan tek bir kullanım durumunu haklı çıkarıyor mu? Bu sorun ben içine koşuyorum. Zaten besteci, npm, yutmak, homurdanıyor, şahsen çardak istemiyorum ve bu uygulamada da homurdanmak istemiyorum.
blamb

Sezgisel bir çözüme ihtiyaç duyan mükemmel bir soru!
Sydwell

Yanıtlar:


297

Genellikle, sunucunuzun dış dünyaya nasıl yapılandırıldığına ilişkin iç yollarınızdan hiçbirini ortaya çıkarmak istemezsiniz. Yapabileceğiniz şey /scripts, sunucunuzda, içinde bulunduğu herhangi bir dizinden dosyalarını alan statik bir yol yapmaktır . Yani, dosyalarınız varsa "./node_modules/bootstrap/dist/". Ardından, sayfalarınızdaki komut dosyası etiketi şöyle görünür:

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

Eğer nodejs ile ekspres kullanıyorsanız, statik bir yol bu kadar basittir:

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

Sonra, herhangi bir tarayıcı istekleri /scripts/xxx.jsirade otomatik olarak getirildiğinden olmak distdizinin geneli __dirname + /node_modules/bootstrap/dist/xxx.js.

Not: NPM'nin daha yeni sürümleri en üst düzeye daha fazla şey koyar, bu kadar derin iç içe yerleştirilmez, bu nedenle NPM'nin daha yeni bir sürümünü kullanıyorsanız, yol adları OP sorusunda ve geçerli yanıtta belirtilenden farklı olacaktır. Ancak, konsept hala aynı. Dosyalar fiziksel olarak sunucu sürücüsünde bulunduğu yeri öğrenmek ve bir yapmak app.use()ile express.static()istemci gerçek sunucu dosya sistemi organizasyonu maruz bırakmakla bu yüzden bu dosyalara sahte yolunu yapmak.


Böyle statik bir yol yapmak istemiyorsanız, muhtemelen genel komut dosyalarını web sunucunuzun işlediği bir yola /scriptsveya kullanmak istediğiniz üst düzey atamaya kopyalamaktan daha iyidir . Genellikle, bu kopyalamayı oluşturma / dağıtım işleminizin bir parçası haline getirebilirsiniz.


Bir dizinde yalnızca belirli bir dosyayı herkese açık hale getirmek istiyorsanız ve bu dizinde bulunan her şeyi değil, her dosya için manuel olarak ayrı yollar oluşturabilirsiniz, express.static()örneğin:

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

Ve bunun için bir rota oluşturma kodu

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

Veya, komut dosyaları için rotaları yine de tanımlamak /scriptsistiyorsanız, bunu yapabilirsiniz:

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

Ve bunun için bir rota oluşturma kodu

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

2
Bunları manuel olarak kopyalamam gerekiyor mu yoksa bunu yapmanın bir Grunt yolu var mı? Ben bir şekilde en iyisi tamamen bootstrap klasörü kopyalamak olacağını düşünüyorum /scriptsçünkü bu şekilde modül içindeki herhangi bir bağımlılık korunur.
Chris

@phpheini - belki de yardımcı olacaktır: stackoverflow.com/questions/18966485/… ve bu npmjs.com/package/grunt-copy
jfriend00

1
@RobertOschler - Hayır, dupleri kontrol etmez. express.static()bulduğu ilk maçı gönderir. Her express.static()deyim yalnızca bir olası eşleşme yolu oluşturduğundan, bir deyimden kopyalar olmamalıdır express.static(). express.static()Her birinin bir eşleşmeye sahip olabileceği birden fazla ifadeniz varsa , kodunuzdaki ilk ifade, eşleşmenin kullanılacağı ifadedir. Ayrıca, gerçekten aynı ada ve express.static()ifadelere göre göreceli yola sahip birden fazla dosyanız olmamalıdır . En iyi uygulama bunu yapmamaktır.
jfriend00

1
@RobertOschler - Kuralsız erişim sağladığınız şey konusunda çok ama çok dikkatli olmalısınız. Genel olarak, yalnızca express.static()SADECE genel dosyaları içeren bir dizini işaret etmelisiniz (alt dizinleri dahil et). Bu yüzden, çok sayıda distdizinin yayınlandığı bir projeyi gerçekten hayal edemiyorum . Bu benim için çok sıradışı görünüyor. Belki belirli bir dosyaya veya 2-3 dosyaya belirli bir rota yapmak istersiniz. Bu durumda, bu dosyaları netleştirmekten sorumlusunuz. script.jsZaten dört dosyaya sahip olmak sana bir yararı olmayacak .
jfriend00

1
@RobertOschler - Eşleştirmek için önlerinde benzersiz bir yol gerekmiyorsa, herhangi bir kodun /script.jstarayıcı tarafından istendiğinde hangisinin sunulacağını bilmesinin bir yolu yoktur . Bu nedenle, soyut yanıt, yinelenen dosya adlarının durumunun var olmasına izin vermemenizdir, çünkü her dosya dizini için benzersiz bir önek gerektirmedikçe çözülebilir bir sorun değildir. Sonra, yinelenen kök adları yine de sorun değil. Ayrıntılı bir öneri ile daha spesifik bir cevap için, kendi sorunuzu kesin ayrıntılarla göndermeniz gerekir.
jfriend00

18

Ben yol npm modülünü kullanmak ve sonra böyle bir şey yapmak:

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

ÖNEMLİ: sistem agnostik yolunu kullanarak yolları birleştirmek için path.join öğesini kullanırız, yani windows ve unix'te farklı yol ayırıcılarımız (/ ve) vardır


yukarıdaki gibi yinelenen işareti, path.join sadece bir ölçü, ancak yine de node_modules dir statik bir yol ekleyerek aynı çözümdür.
blamb

2
"path.join sadece ek bir önlem, ama yine de aynı çözüm" aynı çözüm değil. Açıkçası, sisteme özel birleştirme kullanır (Windows ve Unix'te aklınızda bulundurun / ve \ ayırıcıları)
Alexander Egorov

4
Tamam, ne demek istediğini anlıyorum, evet sistem agnostik olması her zaman iyidir, bunun ne olduğunun farkında değildim. Bunu işaret ettiğiniz için teşekkürler. Bunu sadece :-) kodunu vermek yerine cevabınızdaki cümleye eklemek akıllıca olur, örneğin kodunuzu açıklayın.
blamb

10

Jfriend00 tarafından belirtildiği gibi, sunucu yapınızı göstermemelisiniz. Proje bağımlılık dosyalarınızı benzer bir şeye kopyalayabilirsiniz public/scripts. Bunu, böyle dep-linker ile çok kolay bir şekilde yapabilirsiniz :

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

1
Komut dosyaları srcs gibi bir şey olacaktır /scripts/[package-name]/dist/file.min.js.
Jacob Ford

7

Hızlı ve kolay bir çözüm istiyorsanız (ve yudum yüklüyse).

Benim gulpfile.jsihtiyacım olabilecek herhangi bir dosyayı ./public/modules/dizine koyan basit bir kopyala yapıştır görevi çalıştırıyorum .

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']);

Bunun dezavantajı, otomatik olmamasıdır. Bununla birlikte, tek ihtiyacınız olan birkaç komut dosyası ve stil kopyalanmışsa (ve bir listede tutulursa), bu işi yapmalıdır.


Biri bunu 'scripts': {'install':'yarn gulp copy-modules'}paketlerine ekleyebilir .
Todd

6

'Node_modules' dizini geçerli dizinde olmayabilir, bu nedenle yolu dinamik olarak çözmelisiniz.

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

+1, bunun her durumda işe yarayacağını düşünmüyorum - node_modules alt klasöründe olmayan egan npm bağlantılı modül
Alasdair McLeay

3

Bu soruyu daha kolay bir çözümle güncellemek istiyorum. Düğüm_modüllerine sembolik bir bağlantı oluşturun.

Düğüm_modüllerine herkese açık erişim vermenin en kolay yolu, genel dizininizden düğümü_modüllerinize işaret eden sembolik bir bağlantı oluşturmaktır. Symlink, bağlantının oluşturulduğu her yerde dosyalar varmış gibi yapar.

Örneğin, düğüm sunucusunda statik dosyaları sunmak için kod varsa

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

ve __dirname, statik dosyalarınızın / path / to / app / dist'den sunulması için / path / to / app ifadesini belirtir

ve node_modules / path / to / app / node_modules konumunda, daha sonra mac / linux'da böyle bir sembolik bağlantı oluşturun:

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

ya da pencerelerde böyle:

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

Şimdi aşağıdakiler için bir istek:

node_modules/some/path 

adresindeki dosyayla bir yanıt alacak

/path/to/app/dist/node_modules/some/path 

bu dosyadaki dosya

/path/to/app/node_modules/some/path

/ Path / to / app / dist dizininiz, belki de gulp veya grunt ile bir oluşturma işleminden kaynaklanan parazit nedeniyle güvenli bir konum değilse, bağlantı için ayrı bir dizin ekleyebilir ve aşağıdaki gibi yeni bir serveStatic çağrısı ekleyebilirsiniz:

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

ve düğümde şunu ekleyin:

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

1
Ancak uygulamanızı farklı bir yola taşıdınız ve sembolik bağlantı geçersiz. Veya uygulamanızı farklı bir makinede (test / prod) çalıştırmak istiyorsanız, tekrar oluşturmanız gerekir. Uygulamanıza katkıda bulunan herkes aynı şeyi yapmalıdır. Yukarıdaki çözümlere biraz bakım katar.
mati.o

@ mati.o Göreceli sembolik bağlantılar ne olacak? Bu çözümü seviyorum, ancak sadece göreli sembollerle.
Lukáš Bednařík

3

Herhangi bir temiz çözüm bulamadım (tüm node_modules'lerin kaynağını ortaya çıkarmak istemiyorum), bu yüzden onları kopyalamak için bir Powershell betiği yazdım:

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

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

1

AUTO-INCLUDE dizin html dosyaları için aşağıdaki değişiklikleri yaptım. Böylece klasöre bir dosya eklediğinizde, dosyayı index.html dosyasına eklemenize gerek kalmadan otomatik olarak klasörden alınır.

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

1

Sunucumda ayarladığım şey bu 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>

İyi şanslar...

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.