使用webpack定义全局变量

Ten*_*eff 117 javascript webpack webpack-2 webpack-3

是否可以使用webpack定义一个全局变量,结果如下:

var myvar = {};
Run Code Online (Sandbox Code Playgroud)

我看到的所有示例都使用外部文件 require("imports?$=jquery!./file.js")

pro*_*mer 236

有几种方法来处理全局变量:

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)的WebPack的ProvidePlugin

以下是使用Webpack的ProvidePlugin(它使模块可用作每个模块中的变量以及仅实际使用它的模块)的方法.当您不想import Bar from 'foo'一次又一次地输入时,这非常有用.或者你可以在这里引入像jQuery或lodash这样的包(尽管你可以看看Webpack的外部).

步骤1)创建任何模块.例如,一组全局实用程序将非常方便:

utils.js

export function sayHello () {
  console.log('hello')
}
Run Code Online (Sandbox Code Playgroud)

步骤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'
    })
  ]  

}
Run Code Online (Sandbox Code Playgroud)

现在只需调用utils.sayHello()任何js文件,它应该工作.如果您正在使用Webpack,请确保重新启动您的开发服务器.

注意:不要忘记告诉你的关于全球的信息,所以它不会抱怨.例如,请在此处查看我对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")
})
Run Code Online (Sandbox Code Playgroud)

使用它像:

console.log("Running App version " + VERSION);
if(!BROWSER_SUPPORTS_HTML5) require("html5shiv");
Run Code Online (Sandbox Code Playgroud)

4)使用全局窗口对象(或Node的全局)

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/
Run Code Online (Sandbox Code Playgroud)

你会看到这通常用于polyfills,例如: window.Promise = Bluebird

5)使用像dotenv这样的包

(对于服务器端项目)dotenv包将采用本地配置文件(如果有任何密钥/凭证,您可以将其添加到.gitignore)并将配置变量添加到Node的process.env对象.

// As early as possible in your application, require and configure dotenv.    
require('dotenv').config()
Run Code Online (Sandbox Code Playgroud)

.env在项目的根目录中创建一个文件.以新的形式添加特定于环境的变量NAME=VALUE.例如:

DB_HOST=localhost
DB_USER=root
DB_PASS=s1mpl3
Run Code Online (Sandbox Code Playgroud)

而已.

process.env现在具有您在.env文件中定义的键和值.

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

笔记:

关于Webpack的外部,如果要排除某些模块包含在构建的包中,请使用它.Webpack将使该模块在全球范围内可用,但不会将其放入您的捆绑包中.这对于像jQuery这样的大型库来说很方便(因为树摇动外部包在Webpack中不起作用),在这些库中已经在单独的脚本标签(可能来自CDN)中加载了这些库.

  • +1.我正在重新构建一个应用程序,以利用webpack作为构建工具,这最初对我不起作用,因为我没有在目标文件中包含对我自己的`utils`命名空间的任何引用 - 最初我刚刚放了一个断点在浏览器的源窗口中,我一直在困惑为什么`utils`没有被定义.最后我发现webpack(相当聪明)_only_包含一个模块,如果它的名称空间至少被引用一次.因此,一旦我使用`utils`编写了目标文件的一个实用程序函数,就会包含模块_was_. (3认同)
  • Webpack文档(已更新):https://webpack.js.org/plugins/provide-plugin/ (2认同)
  • 您知道如何在 TypeScript 中使用这种方法吗?如果你使用未声明的变量,它会抛出错误...... (2认同)
  • @prograhammer实际上,我已经找到了解决方案。在应用程序的根目录(通常是* tsconfig.json *所在的位置)中,您需要添加一个名为* global.d.ts *的定义文件。在其中可以声明全局变量,如下所示:`declare const isProduction:bool;`供参考,请参见https://www.typescriptlang.org/docs/handbook/declaration-files/templates/global-d-ts .html (2认同)

Ori*_*lBG 41

我正要问同样的问题.搜索一点,并decyphering的WebPack的文档的一部分之后,我认为,你想要什么output.library,并output.libraryTarget在在webpack.config.js文件中.

例如:

JS/index.js:

var foo = 3;
var bar = true;
Run Code Online (Sandbox Code Playgroud)

webpack.config.js

module.exports = {
   ...
   entry: './js/index.js',
   output: {
      path: './www/js/',
      filename: 'index.js',
      library: 'myLibrary',
      libraryTarget: 'var'
   ...
}
Run Code Online (Sandbox Code Playgroud)

现在,如果您将生成的www/js/index.js文件链接到html脚本标记中,则可以myLibrary.foo从其他脚本中的任何位置进行访问.

  • 我认为这从`index.js`中丢失了`export {foo}`吗? (3认同)

Ric*_*cky 15

使用DefinePlugin.

DefinePlugin允许您创建可在编译时配置的全局常量.

new webpack.DefinePlugin(definitions)
Run Code Online (Sandbox Code Playgroud)

例:

plugins: [
  new webpack.DefinePlugin({
    PRODUCTION: JSON.stringify(true)
  })
  //...
]
Run Code Online (Sandbox Code Playgroud)

用法:

console.log(`Environment is in production: ${PRODUCTION}`);
Run Code Online (Sandbox Code Playgroud)

  • DefinePlugin 具有欺骗性。它不会创建全局变量。相反,它用其他代码字符串替换代码字符串,并且仅在您的包上运行。因此,对于需要真正的“window.*”变量(例如外部脚本)的人来说,DefinePlugin 将不起作用。 (2认同)

Anh*_*yen 12

你可以使用define window.myvar = {}.当你想使用它时,你可以使用likewindow.myvar = 1