Определите глобальную переменную с помощью веб-пакета

138

Можно ли определить глобальную переменную с помощью веб-пакета, чтобы получить что-то вроде этого:

var myvar = {};

Все примеры, которые я видел, использовали внешний файл require("imports?$=jquery!./file.js")

Teneff
источник

Ответы:

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 веб-пакета

Вот как вы можете сделать это с помощью веб-пакета ProvidePlugin (который делает модуль доступным в качестве переменной в каждом модуле и только в тех модулях, где вы его фактически используете). Это полезно, когда вы не хотите продолжать печатать import Bar from 'foo'снова и снова. Или вы можете добавить пакет, такой как глобальный jQuery или lodash (хотя вы можете взглянуть на внешние компоненты Webpack ).

Шаг 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, и он должен работать. Убедитесь, что вы перезапускаете свой dev-сервер, если используете его с Webpack.

Примечание: не забудьте рассказать своему линтеру о глобальном, чтобы он не жаловался. Например, см. Мой ответ для ESLint здесь .

3) Используйте DefinePlugin Webpack

Если вы просто хотите использовать 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, если есть какие-либо ключи / учетные данные) и добавит ваши переменные конфигурации в объект 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 , используйте его, если вы хотите исключить некоторые модули из вашего встроенного комплекта. Webpack сделает модуль глобально доступным, но не добавит его в ваш пакет. Это удобно для больших библиотек, таких как jQuery (потому что внешние пакеты не работают в Webpack ), где они уже загружены на страницу в виде отдельных тегов сценария (возможно, из CDN).

prograhammer
источник
3
+1. Я реструктурирую приложение, чтобы использовать веб-пакет в качестве инструмента для сборки, и это изначально не сработало для меня, потому что я не включил ссылку на свое собственное utilsпространство имен в целевой файл - изначально я только что установил точку останова в браузере окно источника, и я продолжал ломать голову над тем, почему utilsне было определено. В конце концов я обнаружил , что Webpack (довольно шустро) только включает в себя модуль , если его пространство имен раз ссылаются , по крайней мере. Поэтому, как только я сделал предисловие с одной из служебных функций целевого файла utils, модуль был включен.
nb1987
Да, только там, где вы используете его, он делает его доступным. Я поместил это в первую строку ответа, но сделал небольшую корректировку, так что, возможно, она читается лучше. Спасибо за +1!
программер
1
Обратите внимание, что ProvidePlugin на самом деле загружает модули, и если вам просто нужна переменная, она не работает таким образом. Просто используйте externalsвместо этого, если вам нужно создать глобальную переменную. Пример: externals: { 'webpackVariables': `{ serverUrl: '${ env.server }', cordovaBuild: '${ env.cordova }', }`, }, затем используйте это какconst webpackVariables = require('webpackVariables');
Брайан Хаак
1
И знаете ли вы, как я могу использовать этот подход с TypeScript? Там, если вы используете необъявленную переменную, она выдает ошибку ...
knaos
2
@prograhammer На самом деле, я уже нашел решение. В корне вашего приложения, обычно там, где находится ваш tsconfig.json , вам нужно добавить файл определения с именем global.d.ts . В нем вы можете объявить глобальные переменные, например так: declare const isProduction: bool;для справки, проверьте typescriptlang.org/docs/handbook/declaration-files/templates/…
knaos
45

Я собирался задать тот же вопрос. После поиска немного дальше и decyphering части документации WebPack, я думаю , что то , что вы хотите , это output.libraryи output.libraryTargetвwebpack.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из любого другого скрипта.

OriolBG
источник
3
Я думаю, что это отсутствует export { foo }в index.js?
LondonAppDev
myLibrary дает неопределенный в другом файле в моем случае. Можете ли вы помочь мне
RVCoder
17

Используйте DefinePlugin .

DefinePlugin позволяет вам создавать глобальные константы, которые можно настроить во время компиляции.

new webpack.DefinePlugin(definitions)

Пример:

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

Использование:

console.log(`Environment is in production: ${PRODUCTION}`);
Рики
источник
14

Вы можете использовать определить window.myvar = {}. Когда вы хотите использовать его, вы можете использовать какwindow.myvar = 1

Ан Нгуен
источник
Это не работает с EMCAScript 6. Создает ошибку с var window.CKEDITOR_BASEPATH = {};ошибкой «Неожиданный window.
токен
1
Сожалею. Я только что обновил свой ответ. Вы должны varключевое слово. window.CKEDITOR_BASEPATH = {};
Ан Нгуен
Это работает, к сожалению, проблема, с которой я столкнулся, заключается в том, что мне нужно, чтобы он был загружен в пакет до CKEditor, однако Webpack настаивает на том, чтобы помещать его после того, куда бы я его не поместил в мой import / js. : /
Routhinator
2

Я решил эту проблему, установив глобальные переменные в качестве статических свойств для классов, для которых они наиболее актуальны. В ES5 это выглядит так:

var Foo = function(){...};
Foo.globalVar = {};
pasx
источник