node_modules 폴더 안에 스크립트를 포함시키는 방법은 무엇입니까?


275

node_modulesHTML 웹 사이트 에 포함하기위한 모범 사례에 관한 질문이 있습니다.

node_modules폴더 안에 부트 스트랩이 있다고 상상해보십시오 . 이제 웹 사이트의 프로덕션 버전의 경우 node_modules폴더 안에 Bootstrap 스크립트와 CSS 파일을 어떻게 포함 합니까? Bootstrap을 해당 폴더 안에두고 다음과 같은 작업을 수행하는 것이 합리적입니까?

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

아니면 gulp 파일에 규칙을 추가 한 다음 해당 파일을 dist 폴더에 복사해야합니까? 아니면 꿀꺽 꿀꺽 HTML 파일에서 로컬 부트 스트랩을 완전히 제거하고 CDN 버전으로 바꾸는 것이 가장 좋습니까?


2
관련 주제 stackoverflow.com/questions/24397379/... . 그래서 여기에 Questino @Palak Bhansali 하나만 필요하다고 가정하면, 예를 들어 npm에서 직접 부트 스트랩을 생성하는 gulp express 앱이 node_modules에있는 gulp의 파일에 액세스 해야하는 등 gulp express 앱이 유일한 목적으로 bower를 구현하는 것을 정당화합니까? 이것이이 유일한 목적을 위해 지금 bower를 필요로하는 단일 사용 사례를 정당화합니까? 문제가 발생했습니다. 나는 이미 작곡가, npm, gulp, grunt를 사용하고 개인적으로 bower를 원하지 않으며이 응용 프로그램에서도 grunt를 원하지 않습니다.
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()와는 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
수동으로 복사해야합니까, 아니면 그런 방법이 있습니까? 어떻게 든 가장 좋은 /scripts방법 은 부트 스트랩 폴더를 완전히 복사하는 것입니다. 모듈 내부의 모든 종속성이 유지되기 때문입니다.
Chris

@phpheini - 아마도이 도움이 될 것입니다 stackoverflow.com/questions/18966485/...npmjs.com/package/grunt-copy
jfriend00

1
@RobertOschler-아니요. 딥을 확인하지 않습니다. express.static()찾은 첫 번째 일치를 보냅니다. 각 express.static()명령문은 가능한 일치 경로를 하나만 작성 하므로 하나의 express.static()명령문 에서 중복되지 않아야 합니다. express.static()각각 일치 하는 문장 이 여러 개인 경우 코드의 첫 번째 문장이 일치 하는 문장입니다. 또한 실제로 같은 이름과 상대 경로를 가진 파일이 여러 개 있으면 안됩니다 express.static(). 가장 좋은 방법은 그렇게하지 않는 것입니다.
jfriend00

1
@RobertOschler-규제되지 않은 액세스를 제공하는 것에 대해 매우 신중해야합니다. 일반적으로 express.static()공용 파일 만 포함 된 디렉토리 (하위 디렉토리 포함) 만 가리켜 야합니다 . 따라서 많은 dist디렉토리가 게시 된 프로젝트를 상상할 수 없습니다 . 그것은 나에게는 매우 이례적인 것 같습니다. 아마도 특정 파일이나 2-3 파일로 특정 경로를 만들고 싶을 것입니다. 이 경우 해당 파일을 명확하게 구분해야합니다. script.js어쨌든 네 개의 파일 을 갖는 것은 좋지 않습니다 .
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을 사용하여 시스템에 무관 한 방식으로 경로를 결합합니다.


위와 같이 중복으로 표시하면 path.join은 추가 측정 값이지만 node_modules 디렉토리에 정적 경로를 추가하여 동일한 솔루션입니다.
blamb

2
"path.join은 추가 된 측정치이지만 여전히 동일한 솔루션"은 동일한 솔루션이 아닙니다. 엄밀히 말하면 그것은 (염두에 두어야 / 및 \ 분리기 윈도우와 유닉스)에 합류 시스템의 특정을 사용
알렉산더 에고 로프

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.
Jacob Ford

7

빠르고 쉬운 솔루션을 원한다면 (그리고 꿀꺽 꿀꺽 설치 한 경우).

내 디렉토리에 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']);

이것의 단점은 자동화되지 않았다는 것입니다. 그러나 필요한 모든 스크립트와 스타일을 복사하여 (목록에 보관) 필요한 경우이 작업을 수행해야합니다.


'scripts': {'install':'yarn gulp copy-modules'}원사가 패키지 관리자이고 gulp가 패키지에 설치되어 있다고 가정하면 스크립트의 package.json에 이것을 추가 할 수 있습니다 .
Todd

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를 가리키는 기호 링크를 작성하는 것입니다. 심볼릭 링크는 링크가 생성되는 모든 위치에 파일이있는 것처럼 만듭니다.

예를 들어, 노드 서버에 정적 파일을 제공하기위한 코드가있는 경우

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
그러나 앱을 다른 경로로 옮겼으며 심볼릭 링크가 유효하지 않습니다. 또는 다른 컴퓨터 (테스트 / 제품)에서 앱을 실행하려면 다시 만들어야합니다. 앱에 기여한 사람은 모두 동일하게해야합니다. 위의 솔루션보다 약간의 주력을 추가합니다.
mati.o

@ mati.o 상대 심볼릭 링크는 어떻습니까? 나는이 솔루션을 좋아하지만 상대 심볼릭 링크 만 사용합니다.
Lukáš 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.