웹팩으로 전역 변수 정의


138

webpack으로 전역 변수를 정의하여 다음과 같은 결과를 얻을 수 있습니까?

var myvar = {};

내가 본 모든 예제는 외부 파일을 사용하고있었습니다. require("imports?$=jquery!./file.js")

답변:


272

세계에 접근하는 방법에는 여러 가지가 있습니다.

1) 변수를 모듈에 넣습니다.

Webpack은 모듈을 한 번만 평가하므로 인스턴스는 전역으로 유지되며 모듈 간 변경 사항이 적용됩니다. 따라서 a globals.js와 같은 것을 만들고 모든 전역의 객체를 내 보내면 import './globals'이러한 전역에 읽고 쓸 수 있습니다 . 한 모듈로 가져 와서 함수에서 객체를 변경하고 다른 모듈로 가져 와서 함수의 변경 사항을 읽을 수 있습니다. 또한 일이 일어나는 순서를 기억하십시오. Webpack은 먼저 모든 가져 오기를 수행하여에서 시작하는 순서대로로드합니다 entry.js. 그런 다음 실행 entry.js됩니다. 따라서 전역에 대한 읽기 / 쓰기가 중요합니다. 모듈의 루트 범위 또는 나중에 호출되는 함수에 있습니까?

참고 : new매번 인스턴스를 사용하려면 ES6 클래스 를 사용하십시오 . 전통적으로 JS에서는 다음과 같이 클래스를 대문자로 사용합니다 (객체의 소문자가 아닌).
import FooBar from './foo-bar' // <-- Usage: myFooBar = new FooBar()

2) 웹팩의 ProvidePlugin

다음은 Webpack의 ProvidePlugin을 사용하여 수행 할 수있는 방법입니다 (모든 모듈에서 모듈로 변수로 사용 가능하고 실제로 사용하는 모듈에서만 가능). 이것은 계속 타이핑을 계속하고 싶지 않을 때 유용 import Bar from 'foo'합니다. 또는 jQuery 또는 lodash와 같은 패키지를 전역으로 가져올 수 있습니다 (Webpack의 Externals를 볼 수도 있지만 ).

1 단계) 모듈을 만듭니다. 예를 들어, 전역 유틸리티 세트가 유용합니다.

utils.js

export function sayHello () {
  console.log('hello')
}

2 단계) 모듈 별명을 지정하고 ProvidePlugin에 추가하십시오.

webpack.config.js

var webpack = require("webpack");
var path = require("path");

// ...

module.exports = {

  // ...

  resolve: {
    extensions: ['', '.js'],
    alias: {
      'utils': path.resolve(__dirname, './utils')  // <-- When you build or restart dev-server, you'll get an error if the path to your utils.js file is incorrect.
    }
  },

  plugins: [

    // ...

    new webpack.ProvidePlugin({
      'utils': 'utils'
    })
  ]  

}

이제 utils.sayHello()모든 js 파일을 호출 하면 작동합니다. Webpack과 함께 사용하는 경우 dev 서버를 다시 시작하십시오.

참고 : 린터에 글로벌 정보를 알려주는 것을 잊지 마십시오. 예를 들어 ESLint에 대한 내 대답은 여기를 참조하십시오 .

3) Webpack의 DefinePlugin 사용

전역에 문자열 값과 함께 const를 사용하려는 경우이 플러그인을 Webpack 플러그인 목록에 추가 할 수 있습니다.

new webpack.DefinePlugin({
  PRODUCTION: JSON.stringify(true),
  VERSION: JSON.stringify("5fa3b9"),
  BROWSER_SUPPORTS_HTML5: true,
  TWO: "1+1",
  "typeof window": JSON.stringify("object")
})

다음과 같이 사용하십시오.

console.log("Running App version " + VERSION);
if(!BROWSER_SUPPORTS_HTML5) require("html5shiv");

4) 전역 창 객체 (또는 노드의 전역)를 사용하십시오.

window.foo = 'bar'  // For SPA's, browser environment.
global.foo = 'bar'  // Webpack will automatically convert this to window if your project is targeted for web (default), read more here: https://webpack.js.org/configuration/node/

예를 들어 폴리 필에 일반적으로 사용되는 것을 볼 수 있습니다. window.Promise = Bluebird

5) dotenv 와 같은 패키지를 사용하십시오.

(서버 측 프로젝트의 경우) dotenv 패키지는 로컬 구성 파일 (키 / 자격 증명이있는 경우 .gitignore에 추가 할 수 있음)을 가져와 구성 변수를 Node의 process.env 객체에 추가합니다 .

// As early as possible in your application, require and configure dotenv.    
require('dotenv').config()

.env프로젝트의 루트 디렉토리에 파일을 작성하십시오 . 형식으로 새 줄에 환경 별 변수를 추가하십시오 NAME=VALUE. 예를 들면 다음과 같습니다.

DB_HOST=localhost
DB_USER=root
DB_PASS=s1mpl3

그게 다야.

process.env이제 .env파일에 정의한 키와 값이 있습니다.

var db = require('db')
db.connect({
  host: process.env.DB_HOST,
  username: process.env.DB_USER,
  password: process.env.DB_PASS
})

노트:

Webpack의 Externals 와 관련 하여 빌드 된 번들에 일부 모듈이 포함되지 않도록하려면 사용하십시오. Webpack은 모듈을 전 세계적으로 사용할 수있게하지만 번들에 넣지 않습니다. 이것은 jQuery와 같은 큰 라이브러리에 유용합니다 (웹 패키지 에서는 트리 흔들리는 외부 패키지 가 작동하지 않기 때문에 ). 이들은 이미 별도의 스크립트 태그 (아마도 CDN에서)로 페이지에로드되어 있습니다.


3
+1. 웹 패키지를 빌드 도구로 활용하도록 앱을 재구성하고 있으며 utils대상 파일에 내 네임 스페이스에 대한 참조가 포함되어 있지 않기 때문에 처음에는 작동하지 않았습니다. 처음에는 브라우저의 중단 점을 설정했습니다. 소스 창과 나는 왜 utils정의되지 않은지 계속해서 수수께끼를 부었다 . 마지막으로 웹 네임 스페이스가 적어도 한 번 참조되는 경우 웹 패키지 (스마트하게는 아님) 모듈을 포함 한다는 것을 알았 습니다. 따라서 대상 파일의 유틸리티 기능 중 하나를로 시작 utils하면 모듈 포함되었습니다.
nb1987

예, 사용하는 곳에서만 사용 가능합니다. 나는 그것을 대답의 첫 줄에 넣었지만 약간 조정하여 더 잘 읽을 수 있습니다. +1 주셔서 감사합니다!
prograhammer

1
ProvidePlugin은 실제로 모듈을로드하며 변수 만 필요한 경우에는 작동하지 않습니다. externals전역 변수를 만들어야하는 경우 대신 사용 하십시오. 예 : externals: { 'webpackVariables': `{ serverUrl: '${ env.server }', cordovaBuild: '${ env.cordova }', }`, }, 다음으로 사용const webpackVariables = require('webpackVariables');
브라이언 HAAK

1
TypeScript에서이 방법을 어떻게 사용할 수 있는지 알고 있습니까? 선언되지 않은 변수를 사용하면 오류가 발생합니다.
knaos

2
@prograhammer 사실, 나는 이미 해결책을 찾았습니다. 일반적으로 tsconfig.json 이 있는 애플리케이션의 루트에서 global.d.ts 라는 정의 파일을 추가해야합니다 . 그것으로 당신은 다음과 같은 전역 변수를 선언 할 수 있습니다 : declare const isProduction: bool;참조를 위해 이것을 확인하십시오 typescriptlang.org/docs/handbook/declaration-files/templates/…
knaos

45

나는 똑같은 질문을하려고했다. 웹팩의 문서의 일부를 조금 더를 검색하고 decyphering 후 나는 무엇을 당신이 원하는 것은이라고 생각 output.library하고 output.libraryTargetwebpack.config.js파일.

예를 들면 다음과 같습니다.

js / index.js :

var foo = 3;
var bar = true;

webpack.config.js

module.exports = {
   ...
   entry: './js/index.js',
   output: {
      path: './www/js/',
      filename: 'index.js',
      library: 'myLibrary',
      libraryTarget: 'var'
   ...
}

이제 생성 된 www/js/index.js파일을 html 스크립트 태그로 링크하면 myLibrary.foo다른 스크립트의 어느 곳에서나 액세스 할 수 있습니다 .


3
나는 이것이 ~ export { foo }에서 빠졌다고 생각 한다 index.js.
LondonAppDev

myLibrary는 필자의 경우 다른 파일에 undefined를 제공합니다. 당신이 도움을 기쁘게 할 수 나
RVCoder

17

DefinePlugin을 사용하십시오 .

DefinePlugin을 사용하면 컴파일 타임에 구성 할 수있는 전역 상수를 만들 수 있습니다.

new webpack.DefinePlugin(definitions)

예:

plugins: [
  new webpack.DefinePlugin({
    PRODUCTION: JSON.stringify(true)
  })
  //...
]

용법:

console.log(`Environment is in production: ${PRODUCTION}`);

14

define을 사용할 수 있습니다 window.myvar = {}. 사용하고 싶을 때처럼 사용할 수 있습니다window.myvar = 1


EMCAScript 6에서는 작동하지 않습니다. var window.CKEDITOR_BASEPATH = {};이후 오류가 "예기치 않은 토큰"인 오류가 발생합니다window.
Routhinator

1
죄송합니다. 방금 답변을 업데이트했습니다. 당신은 var키워드 해야 합니다. window.CKEDITOR_BASEPATH = {};
Anh Nguyen

불행히도 내가 겪고있는 문제는 CKEditor 전에 번들에로드해야한다는 것입니다. 그러나 Webpack은 가져 오기 / js의 위치에 관계없이 그것을 넣을 것을 주장합니다. : /
Routhinator 2016 년

2

전역 변수를 가장 관련이있는 클래스의 정적 속성으로 설정 하여이 문제를 해결했습니다. ES5에서는 다음과 같습니다.

var Foo = function(){...};
Foo.globalVar = {};
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.