웹팩에서 jQuery 플러그인 종속성 관리


451

내 응용 프로그램에서 Webpack을 사용하고 있는데 모든 JavaScript 파일 / 코드에 대해 bundle.js와 jQuery 및 React와 같은 모든 라이브러리에 대해 vendor.js라는 두 개의 진입 점을 만듭니다. jQuery를 종속 플러그인으로 사용하고 vendor.js에도 플러그인을 사용하려면 어떻게해야합니까? 해당 플러그인에 여러 종속성이있는 경우 어떻게합니까?

현재이 jQuery 플러그인을 사용하려고합니다-https: //github.com/mbklein/jquery-elastic . Webpack 문서에는 providePlugin 및 imports-loader가 언급 되어 있습니다. providePlugin을 사용했지만 여전히 jQuery 객체를 사용할 수 없습니다. 내 webpack.config.js의 모습은 다음과 같습니다.

var webpack = require('webpack');
var bower_dir = __dirname + '/bower_components';
var node_dir = __dirname + '/node_modules';
var lib_dir = __dirname + '/public/js/libs';

var config = {
    addVendor: function (name, path) {
        this.resolve.alias[name] = path;
        this.module.noParse.push(new RegExp(path));
    },
    plugins: [
        new webpack.ProvidePlugin({
            $: "jquery",
            jquery: "jQuery",
            "window.jQuery": "jquery"
        }),
        new webpack.optimize.CommonsChunkPlugin('vendors', 'vendors.js', Infinity)
    ],
    entry: {
        app: ['./public/js/main.js'],
        vendors: ['react','jquery']
    },
    resolve: {
        alias: {
            'jquery': node_dir + '/jquery/dist/jquery.js',
            'jquery.elastic': lib_dir + '/jquery.elastic.source.js'
        }
    },
    output: {
        path: './public/js',
        filename: 'bundle.js'
    },
    module: {
        loaders: [
            { test: /\.js$/, loader: 'jsx-loader' },
            { test: /\.jquery.elastic.js$/, loader: 'imports-loader' }
        ]
    }
};
config.addVendor('react', bower_dir + '/react/react.min.js');
config.addVendor('jquery', node_dir + '/jquery/dist/jquery.js');
config.addVendor('jquery.elastic', lib_dir +'/jquery.elastic.source.js');

module.exports = config;

그러나 그럼에도 불구하고 브라우저 콘솔에서 여전히 오류가 발생합니다.

잡히지 않은 ReferenceError : jQuery가 정의되지 않았습니다

마찬가지로 imports-loader를 사용하면 오류가 발생합니다.

요구가 정의되지 않았습니다 '

이 줄에 :

var jQuery = require("jquery")

그러나 vendor.js 파일에 플러그인을 추가하지 않고 다른 JavaScript 코드 파일을 포함하는 방법과 같이 일반적인 AMD 방식으로 필요할 때 동일한 플러그인을 사용할 수 있습니다.

define(
[
    'jquery',
    'react',
    '../../common-functions',
    '../../libs/jquery.elastic.source'
],function($,React,commonFunctions){
    $("#myInput").elastic() //It works

});

그러나 jquery.elastic.source.js가 bundle.js의 JavaScript 코드와 함께 번들로 제공되고 모든 jQuery 플러그인이 vendor.js 번들에 포함되기를 원하기 때문에 이것은 내가하고 싶은 것이 아닙니다. 어떻게 이것을 달성 할 수 있습니까?


3
이것이 문제인지 확실하지 않지만 windows.jQuery를 "window.jQuery": "jquery"로 변경해야합니다. webpack의 웹 사이트에는 오타가 있습니다.
Alex Hawkins

@AlexHawkins 오 그래, 나는 그것을 알아 차리고 고쳤다. 지적 해 주셔서 감사합니다!
booleanhunter

답변:


771

레거시 공급 업체 모듈을 포함시키는 방법에 대해 서로 다른 접근 방식을 혼합했습니다. 이것이 내가 다루는 방법입니다.

1. 축소되지 않은 CommonJS / AMD보다 선호 dist

대부분의 모듈 dist은 해당 main필드에 버전을 연결합니다 package.json. 이것은 대부분의 개발자에게 유용하지만, 웹팩의 경우 src웹팩이 종속성을 더 잘 최적화 할 수 있기 때문에 (예 :을 사용하는 경우 DedupePlugin) 웹 앨범 버전의 별명을 지정하는 것이 좋습니다 .

// webpack.config.js

module.exports = {
    ...
    resolve: {
        alias: {
            jquery: "jquery/src/jquery"
        }
    }
};

그러나 대부분의 경우 dist버전도 잘 작동합니다.


2.를 사용하여 ProvidePlugin암시 적 전역을 주입합니다

대부분의 기존 모듈의 jQuery 플러그인에서처럼, 특정 전역의 존재에 의존 $하거나 jQuery. 이 시나리오에서는 var $ = require("jquery")전역 $식별자 가 발생할 때마다 앞에 추가되도록 웹팩을 구성 할 수 있습니다 .

var webpack = require("webpack");

    ...

    plugins: [
        new webpack.ProvidePlugin({
            $: "jquery",
            jQuery: "jquery"
        })
    ]

3. imports-loader 를 사용하여 구성this

일부 기존 모듈에 의존 this되는 window객체입니다. 이는 모듈이 CommonJS 컨텍스트에서 this같을 때 문제가됩니다 module.exports. 이 경우 대체 할 수 있습니다 this으로 수입 로더 .

실행 npm i imports-loader --save-dev

module: {
    loaders: [
        {
            test: /[\/\\]node_modules[\/\\]some-module[\/\\]index\.js$/,
            loader: "imports-loader?this=>window"
        }
    ]
}

수입 로더는 또한 모든 종류의 변수를 수동으로 주입하는 데 사용될 수 있습니다. 그러나 대부분 ProvidePlugin암시 적 글로벌에 대해서는 더 유용합니다.


4. imports-loader 를 사용하여 AMD를 비활성화하십시오

AMD, CommonJS 및 레거시와 같은 다양한 모듈 스타일을 지원하는 모듈이 있습니다. 그러나 대부분의 경우 처음으로 확인한 define다음 기발한 코드를 사용하여 속성을 내 보냅니다. 이 경우을 설정하여 CommonJS 경로를 강제 실행하는 데 도움이 될 수 define = false있습니다.

module: {
    loaders: [
        {
            test: /[\/\\]node_modules[\/\\]some-module[\/\\]index\.js$/,
            loader: "imports-loader?define=>false"
        }
    ]
}

5. 스크립트 로더 를 사용하여 스크립트 를 전체적으로 가져옵니다.

전역 변수에 신경 쓰지 않고 레거시 스크립트가 작동하기를 원한다면 스크립트 로더를 사용할 수도 있습니다. 마치 <script>태그 를 통해 포함 된 것처럼 전역 컨텍스트에서 모듈을 실행합니다 .


6. noParse큰 dist를 포함하는 데 사용

AMD / CommonJS 버전의 모듈이없고를 포함하려는 dist경우이 모듈을로 표시 할 수 있습니다 noParse. 그런 다음 webpack은 구문 분석하지 않고 모듈을 포함하므로 빌드 시간을 향상시키는 데 사용할 수 있습니다. 이는 ,와 같이 AST가 필요한 기능이 ProvidePlugin작동하지 않음을 의미합니다.

module: {
    noParse: [
        /[\/\\]node_modules[\/\\]angular[\/\\]angular\.js$/
    ]
}

3
ProvidePlugin모든 파일에 주어진 식별자의 모든 항목에 적용됩니다. 은 imports-loader특정 파일에만 적용 할 수 있지만 동일한 변수 / 종속성에 대해 둘 다 사용해서는 안됩니다.
Johannes Ewald

5
나는 이것으로 혼란스러워합니다. jquery는 실제로 어디에서 왔습니까? 로컬 또는 CDN? 그것이 필요한지 불분명하다. webpack을 사용하여 jquery를 프로젝트에 통합하는 실제 단계는 무엇입니까? CDN을 통해 사용 가능한 버전을 무시합니까?
HelpMeStackOverflowMyOnlyHope 0시 17 분

2
CDN의 모든 것이 웹팩 범위를 벗어나므로 로컬 jquery 설치를 나타냅니다. Jquery가 필요할 수 있습니다. Jquery를 통합하는 데 필요한 특별한 단계가 없습니다. 이 질문은 전역 $변수 에 의존하는 jquery 플러그인을 통합하는 방법에 관한 것 입니다.
Johannes Ewald

8
이 모든 것이 여전히 작동하지 않았습니다. 그런 다음 추가했습니다 : "module": { "loaders": [ { test: require.resolve("jquery"), loader: "expose?$!expose?jQuery" },제대로 작동했습니다.
musicformellons

5
jquery 패키지를 포함 시키려면이 모든 작업을 수행하십시오. 다시 걸프 빌드로 돌아갑니다
Rahul Gupta

89

jquery에 대한 전역 액세스의 경우 몇 가지 옵션이 있습니다. 가장 최근의 웹팩 프로젝트에서 jquery에 대한 전역 액세스를 원했기 때문에 플러그인 선언에 다음을 추가했습니다.

 plugins: [
    new webpack.ProvidePlugin({
      $: "jquery",
      jQuery: "jquery"
    })
  ]

이는 전역 참조 $ 및 jQuery를 통해 JavaScript 소스 코드 내에서 jquery에 액세스 할 수 있음을 의미합니다.

물론, npm을 통해 jquery를 설치해야합니다.

$ npm i jquery --save

이 접근법의 실제 예제를 보려면 github에서 내 앱을 포크하십시오.


2
이유를 설명하는 투표를 다운 그레이드하는 경우 의견을 남겨 주시기 바랍니다. 위의 정보는 정확합니다. 위의 접근 방식을 사용하여 github.com/arcseldon/react-babel-webpack-starter-app 에서 작동하는 앱을 참조하십시오 .
arcseldon

나는 downvoter가 아니지만 아마도 ProvidePlugin제안한 솔루션이 이미 제안 되었기 때문일 수 있습니다.
Léo Lam

@ LéoLam-귀하의 의견에 감사드립니다. 귀하의 요점에 감사드립니다-나는 별도의 문의를 통해 답변을 추론하고 여기에서 스 니펫을 공유했습니다. 당신은 옳습니다. 공식 답변은이 옵션을 다루고 있습니다.
arcseldon

1
그것은 일하고 그러나 나는이 경고를 얻을 : ./~/jQuery/dist/jquery.js There is another module with an equal name when case is ignored.와와 같은 하나./~/jquery/dist/jquery.js
pistou

7
'window.jQuery': 'jquery'ms-signalr-client npm 패키지를로드하려면 해당 목록 에 추가 해야했습니다. 나는 또한 'window.$': 'jquery'좋은 측정 을 위해 넣었다 :)
Sammi

57

나는 당신이하려는 일을 잘 이해하고 있는지 모르겠지만 jQuery가 전역 컨텍스트 (창)에 있어야하는 jQuery 플러그인을 사용해야했고 다음을 내 안에 넣었습니다 entry.js.

var $ = require('jquery');
window.jQuery = $;
window.$ = $;

의 I는 내가 원하는 위치 요구해야 jqueryplugin.min.js하고 window.$예상대로 플러그인 확장됩니다.


2
기본적으로 noParse 조건과 함께 ProvidePlugin을 사용하는 실수를 범했습니다. 답변의 6 번 포인트에 명시된대로 NoParse를 수행하면 ProvidePlugin과 같은 플러그인이 작동하지 않습니다. 코드에서 그 실수를 볼 수 있습니다
booleanhunter

예, 스크립트 로더를 통해 각도 1.x를 가져 오는 경우 플러그인 제공 등보다 플러그인에서 더 일관되게 작동한다는 것을 알았습니다.
트래커 1

27

나는 일을 노출하면서 잘 작동 가지고 $jQuery웹팩 3.8.1 및 다음 글로벌 변수로.

jQuery를 프로젝트 종속성으로 설치하십시오. @3.2.1최신 버전 설치 를 생략 하거나 다른 버전을 지정할 수 있습니다 .

npm install --save jquery@3.2.1

설치 expose-loader설치되어 있지 않은 경우 개발 의존한다.

npm install expose-loader --save-dev

jQuery를로드하고 노출하도록 Webpack을 구성하십시오.

// webpack.config.js
const webpack = require('webpack')

module.exports = {
  entry: [
    // entry bits
  ],
  output: {
    // output bits
  },
  module: {
    rules: [
      // any other rules
      {
        // Exposes jQuery for use outside Webpack build
        test: require.resolve('jquery'),
        use: [{
          loader: 'expose-loader',
          options: 'jQuery'
        },{
          loader: 'expose-loader',
          options: '$'
        }]
      }
    ]
  },
  plugins: [
    // Provides jQuery for other JS bundled with Webpack
    new webpack.ProvidePlugin({
      $: 'jquery',
      jQuery: 'jquery'
    })
  ]
}

5
expose-loader제대로 작동 하려면 설치가 필요하다는 사실을 잊었습니다.npm install expose-loader --save-dev
Paulo Griiettner

4
이것은 나를 위해 일했습니다. jquery : 3.3.1, 노출 로더 : 0.7.5, 웹팩 : 4.20.2
AKT

expose-loaded나를 위해 그것을했다. 컴파일 타임에 오류가 발생하지 않았지만 Chrome 개발자 도구에서 오류가 발생했습니다. 이제 해결되었습니다.
Johan Vergeer

감사합니다! "jquery": "^ 3.4.1"및 "webpack": "^ 4.41.5"와 함께 작동했습니다. jpack이 Webpack과 함께 작동하게하는 것이 그렇게 어리석지 않아야합니까?
Carles Alcolea

18

이것을 webpack.config.js의 플러그인 배열에 추가하십시오

new webpack.ProvidePlugin({
    'window.jQuery': 'jquery',
    'window.$': 'jquery',
})

그런 다음 jquery가 정상적으로 필요합니다.

require('jquery');

고통이 계속해서 다른 스크립트가 그것을 볼 수 있다면 (JS 항목을 통해) 전역 컨텍스트에 명시 적으로 배치하십시오.

window.$ = jQuery;

18

webpack.config.js 파일에서 아래를 추가하십시오.

 var webpack = require("webpack");
 plugins: [
    new webpack.ProvidePlugin({
        $: "jquery",
        jQuery: "jquery"
    })
 ],

npm을 사용하여 jQuery를 설치하십시오.

$ npm i jquery --save

app.js 파일에서 아래 줄을 추가하십시오.

import $ from 'jquery';
window.jQuery = $;
window.$ = $;

이것은 나를 위해 일했습니다. :)


예전의 경우이 행동은 어떻게됩니까? app.js와 jquery-module.js 모두 jquery가 필요합니까? 저는 jquery13981378127 및 jquery12389723198을 창에서 인스턴스로 얻습니까?
Martea

8

제공된 답변 중 일부를 시도했지만 그중 아무것도 작동하지 않는 것 같습니다. 그런 다음 이것을 시도했습니다.

new webpack.ProvidePlugin({
    'window.jQuery'    : 'jquery',
    'window.$'         : 'jquery',
    'jQuery'           : 'jquery',
    '$'                : 'jquery'
});

사용중인 버전에 관계없이 작동하는 것 같습니다


+1은 여기에 추가 된 전역이 자동으로 창에 설정 될 것이라는 오해 인 것 같습니다.
제임스

맞습니다. 이것은 창 개체에 추가되지 않습니다. 웹팩 안에 창 별칭을 만듭니다. 따라서 $웹팩 필수 파일 외부 에서 사용하려고하면 정의되지 않습니다.
Cam Tullos

7

이것은 웹팩 3 에서 작동합니다 .

webpack.config.babel.js 파일에서 :

resolve: {
    alias: {
         jquery: "jquery/src/jquery"
    },
 ....
}

그리고 ProvidePlugin을 사용하십시오.

new webpack.ProvidePlugin({
        '$': 'jquery',
        'jQuery': 'jquery',
    })

1
webpack의 새로운 기능 (예 : 나와!)은 "resolve"가 webpack.config.js의 module.exports = {}에서 entry, output, plugins, module 등과 같습니다.
DavGarcia

1
그리고 새로운 webpack.ProvidePlugin은 plugins 배열에 들어갑니다.
DavGarcia

2

내가 찾은 최고의 솔루션은 다음과 같습니다.

https://github.com/angular/angular-cli/issues/5139#issuecomment-283634059

기본적으로 typings.d.ts에 더미 변수를 포함시키고 코드에서 "import * as $ from 'jquery"를 제거한 다음 jQuery 스크립트의 태그를 SPA html에 수동으로 추가해야합니다. 이렇게하면 웹 팩이 방해가되지 않으며 모든 스크립트에서 동일한 전역 jQuery 변수에 액세스 할 수 있어야합니다.


2

이것은 webpack.config.js에서 나를 위해 작동합니다.

    new webpack.ProvidePlugin({
        $: 'jquery',
        jQuery: 'jquery',
        'window.jQuery': 'jquery'
    }),

다른 자바 스크립트 또는 HTML에 다음을 추가하십시오.

global.jQuery = require('jquery');

0

편집 : 때로는 웹 팩을 간단한 웹 프로젝트의 모듈 번들로 사용하여 코드를 체계적으로 유지하려고합니다. 다음 솔루션은 웹팩 설정에 많은 시간을 소비하지 않고 외부 라이브러리가 모듈 내에서 예상대로 작동하기를 원하는 사람들을위한 것입니다. (-1 이후 편집)

여전히 어려움을 겪고 있거나 외부 구성 / 추가 웹 팩 플러그인 구성을 피하려는 경우 빠르고 간단한 (es6) 솔루션 :

<script src="cdn/jquery.js"></script>
<script src="cdn/underscore.js"></script>
<script src="etc.js"></script>
<script src="bundle.js"></script>

모듈 내부 :

const { jQuery: $, Underscore: _, etc } = window;
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.