node_modulesフォルダー内にあるスクリプトを含める方法は?


275

node_modulesHTML Webサイトに組み込むためのベストプラクティスについて質問があります。

node_modulesフォルダー内にBootstrapがあるとします。Webサイトの製品版では、node_modulesフォルダー内にあるBootstrapスクリプトとCSSファイルをどのように含めるのですか?Bootstrapをそのフォルダー内に残して、次のようなことをするのは理にかなっていますか?

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

または、私のgulpファイルにルールを追加して、それらのファイルをdistフォルダーにコピーする必要がありますか?それとも、どうにかしてHTMLファイルからローカルブートストラップを完全に削除してCDNバージョンに置き換えるのが最善でしょうか。


2
関連トピックstackoverflow.com/questions/24397379/…。SOはquestino @Palak Bhansaliをここに配置します。1つの必要性のみを前提として、たとえば、gulpエクスプレスアプリがnpmから直接ブートストラップをインストールしていて、node_modulesにあるgulp内のファイルにアクセスする必要がある場合など、この唯一の目的でバウアーを実装することは正当化されますか。これは、この唯一の目的のために今バウアーを必要とする単一のユースケースを正当化しますか?それは私が実行している問題です。私はすでにcomposer、npm、gulp、gruntを使用しています。個人的にbowerを必要としないでください。
blamb

直感的な解決策を必要とする素晴らしい質問!
Sydwell

回答:


297

通常、サーバーがどのように構造化されているかについての内部パスを外部に公開したくありません。できることは/scripts、サーバーに静的ルートを作成して、ファイルが存在するディレクトリからファイルをフェッチすることです。つまり、ファイルがにある場合です"./node_modules/bootstrap/dist/"。次に、ページのスクリプトタグは次のようになります。

<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

注:NPMの新しいバージョンでは、ネストの深さが浅いため、最上位に多くのものが配置されているため、新しいバージョンのNPMを使用している場合、パス名はOPの質問および現在の回答に示されているものとは異なります。しかし、コンセプトは同じです。サーバードライブ上のファイルが物理的にどこにあるかがわかります。実際のサーバーファイルシステム構成をクライアントに公開しないように、これらのファイルへの疑似パスを作成するためにapp.use()with express.static()を作成します。


このような静的ルートを作成したくない場合は、Webサーバーが使用するパス、/scriptsまたは使用したいトップレベルの指定にパブリックスクリプトをコピーする方が良いでしょう。通常、このコピーをビルド/デプロイメントプロセスの一部にすることができます。


ディレクトリで特定のファイルを1つだけ公開し、そのディレクトリ内のすべてのファイルを公開する必要がない場合は、次の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
これらを手動でコピーする必要がありますか、それともGruntでそれを行う方法はありますか?どういうわけか、/scriptsモジュール内の依存関係が維持されるため、ブートストラップフォルダを完全にコピーするのが最善だと思います。
Chris

@phpheini-おそらくこれが役立ちます:stackoverflow.com/questions/18966485/…そしてこれはnpmjs.com/package/grunt-copy
jfriend00

1
@RobertOschler-いいえ、重複をチェックしません。 express.static()見つかった最初の一致を送信します。各express.static()ステートメントは一致する可能性のあるパスを1つだけ作成するため、1つのexpress.static()ステートメントからの重複はありません。express.static()それぞれが一致する可能性のある複数のステートメントがある場合、コード内の最初のステートメントは、一致が使用されるステートメントです。また、express.static()ステートメントによって到達可能な同じ名前と相対パスを持つ複数のファイルを実際に持つべきではありません。ベストプラクティスは、これを行わないことです。
jfriend00

1
@RobertOschler-規制されていないアクセスを提供する場合は、非常に慎重に行う必要があります。一般に、express.static()パブリックファイルのみを含むディレクトリ(サブディレクトリを含む)のみを指定する必要があります。だから、dist公開されているディレクトリがたくさんあるプロジェクトを本当に想像することはできません。それは私には非常に珍しいようです。おそらく、特定のファイルまたは2〜3個のファイルへの特定のルートを作成する必要があります。その場合、それらのファイルを明確にする責任があります。script.jsとにかく4つのファイルを用意しても、あまり効果はありません。
jfriend00

1
@RobertOschler-一致するためにそれらの前に一意のパスを要求しないようにした場合/script.js、ブラウザから要求されたときにどのコードを提供するかをコードが知る方法はありません。したがって、抽象的な答えは、ファイルの各ディレクトリに一意のプレフィックスが必要でない限り、解決可能な問題ではないため、ファイル名が重複している状況を許すべきではないということです。そうすれば、ルート名が重複しても問題はありません。詳細な推奨事項でより具体的な回答を得るには、正確な詳細を含む質問を投稿する必要があります。
jfriend00

18

私はパスnpmモジュールを使用し、次のようなことをします:

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

重要: path.joinを使用して、システムに依存しない方法でパスを結合します。つまり、WindowsとUNIXでは、異なるパス区切り文字(/および)を使用します


上記のように複製をマークすると、path.joinは追加されたメジャーですが、node_modulesディレクトリに静的パスを追加することによる同じソリューションです。
blamb

2
「path.joinは追加されたメジャーですが、同じソリューションです」同じソリューションではありません。厳密に言えば、システム固有の結合を使用します(WindowsとUNIXでは/と\の区切り文字に注意してください)
Alexander Egorov

4
ええ、私はあなたの要点を理解しています。そうです、システムにとらわれないことは常に良いことです。それが何であるかは知りませんでした。ご指摘いただきありがとうございます。単にコードを提供するのではなく、回答の文にそれを追加するのが賢明でしょう:-)たとえば、コードを説明します。
blamb

10

jfriend00で述べたように、サーバー構造を公開しないでください。プロジェクトの依存関係ファイルをなどにコピーできますpublic/scripts。これは、次のようなdep-linkerを使用して非常に簡単に行うことができます。

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

1
その場合、スクリプトsrcは次のようになります/scripts/[package-name]/dist/file.min.js
ジェイコブフォード

7

迅速かつ簡単なソリューションが必要な場合(そして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']);

これの欠点は、自動化されないことです。ただし、必要なのは、コピーされた(およびリストに保持されている)いくつかのスクリプトとスタイルだけであれば、これで十分です。


これをスクリプトのpackage.jsonに追加でき'scripts': {'install':'yarn gulp copy-modules'}ます。yarnがパッケージマネージャーで、gulpがパッケージにインストールされていると仮定します。
トッド

6

ディレクトリ 'node_modules'は現在のディレクトリにない可能性があるため、動的にパスを解決する必要があります。

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

+1。ただし、これがすべてのケースで機能するとは思いませんが、たとえば、node_modulesサブフォルダにないegan npmリンクモジュール
Alasdair McLeay

3

この質問をより簡単な解決策で更新したいと思います。node_modulesへのシンボリックリンクを作成します。

node_modulesへのパブリックアクセスを許可する最も簡単な方法は、パブリックディレクトリ内からnode_modulesを指すシンボリックリンクを作成することです。symlinkは、リンクが作成された場所にファイルが存在するかのように作成します。

たとえば、ノードサーバーに静的ファイルを提供するコードがある場合

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

またはWindowsでこれのように:

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呼び出しを追加できます。

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

ノードに追加:

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

1
ただし、アプリを別のパスに移動したため、シンボリックリンクは無効です。または、別のマシン(test / prod)でアプリを実行したい場合は、再度作成する必要があります。アプリの寄稿者も同じようにする必要があります。それは、上記のソリューションにいくつかの主要な要素を追加します。
mati.o 2016

@ mati.o相対シンボリックリンクはどうですか?私はこの解決策が好きですが、相対的なシンボリックリンクがある場合のみです。
ルカシュBednařík

3

クリーンなソリューションが見つからなかった(すべてのnode_modulesのソースを公開したくない)ので、それらをコピーするPowershellスクリプトを作成しました。

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

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

1

以下の変更を行って、インデックスhtmlのファイルをAUTO-INCLUDEしました。そのため、フォルダーにファイルを追加すると、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>
<% } %>

1

これは私の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>

幸運を...

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.