公开通过 webpack 捆绑的 javascript 个全局变量
Expose javascript globals bundled via webpack
问题
我觉得这应该比现在更直接。我需要从前端访问我所有的 javascript 库,因为我正在将它集成到一个旧系统中,所以我无法从前端调用 require("bundle.js");
。 捆绑文件全局范围内的所有内容 必须可以从前端页面的全局范围访问,通过 <script>
标签导入它们。
所以我需要改变旧的:
<script src="js/jquery.js"></script>
<script src="js/silly.js"></script>
<script>
$(silly()); // Some function in silly.js's global scope
</script>
给新的:
<script src="js/bundle.js"></script>
<script>
$(silly()); // Some function in silly.js's global scope
</script>
我尝试过的事情
expose-loader: 如果我没有 100 个我不想明确告诉它看起来的全局变量,这将完全有效
为.
ProvidePlugin: 只真正让库看到其他库。我也无法用我当前的设置明确地编写我需要的所有全局变量(不断添加更多)。
我需要的
所以为了更清楚起见,我需要我的 webpack.config.js
看起来像以下选项之一:
// Everything is wrapped in module.exports and other irrelevant things
plugins: [
new StaticLibraryMergerSuperNeatPlugin("js/*.js")
]
// ...
或者:
rules: [
{
test: /\.js$/,
use: [
"neat-merging-cool-loader",
"babel-loader"]
}
]
// ...
我做错了吗?
我缺少明显的解决方案吗?
Tl;博士:
如何从捆绑的 js 文件创建全局变量,当通过 <script src="js/bundle.js"></script>
在前端 html 页面上导入时暴露在全局范围内?
顺便说一句:如果有人是 webpack 的传奇人物并且知道为什么这是一个糟糕的方法,请在下面 post 进行简短的解释,这样我就可以解决问题。
这是我如何在自己的网站上执行此操作的示例。我不确定这是唯一的方法,还是最好的方法,但它干净、简单,而且对我有用。
重要的旁注 - 在 window 上声明事物时使用 window["propName"]
因为当你 运行 webpack -p
它会丑化任何非字符串,因此如果您将其定义为 window.propName
,它可能会更改为类似 s.c
的内容,而您的其余代码不知道它是什么。用括号表示法将其声明为字符串将强制 webpack 保持名称完整,以便您可以从任何地方使用相同的名称访问它。
site.ts(可以是.js,无所谓)
/*************************/
/*** JQUERY + JQUERYUI ***/
/*************************/
/* var declaration for typescript - not needed if not using .ts */
declare var $:JQueryStatic; declare var jQuery:JQueryStatic;
window["$"] = window["jQuery"] = require("jquery");
require("jquery-ui/effects/effect-slide");
require("jquery-ui/widgets/autocomplete");
require("jquery-ui/widgets/button");
require("jquery-ui/widgets/datepicker");
require("jquery-ui/widgets/tooltip");
/*************************/
/* END JQUERY + JQUERYUI */
/*************************/
/***************/
/*** ANGULAR ***/
/***************/
/* var declaration for typescript - not needed if not using .ts */
declare var angular:ng.IAngularStatic;
window["angular"] = require("angular");
require("angular-sanitize");
/***************/
/* END ANGULAR */
/***************/
/************************/
/*** MISC THIRD-PARTY ***/
/************************/
window["moment"] = require("moment");
window["saveAs"] = require("FileSaver").saveAs;
window["JSZip"] = require("jszip");
/************************/
/* END MISC THIRD-PARTY */
/************************/
/* var declaration for typescript - not needed if not using .ts */
declare var globals:Globals;
window["globals"] = require("./globals");
Layout.html(每页加载)
.....
<script src="/dist/scripts/site.bundle.js"></script>
.....
webpack.config.js
var path = require('path');
var resolve = path.resolve;
var AssetsPlugin = require('assets-webpack-plugin');
var WebpackCleanupPlugin = require("webpack-cleanup-plugin");
'use strict';
var babelOptions = {
"presets": [
[
"es2015",
{
"modules": false
}
],
"es2016"
]
};
module.exports = [{
cache: true,
context: resolve('Scripts'),
devtool: "source-map",
entry: {
site: './site.ts',
},
output: {
path: path.resolve(__dirname, './dist/scripts'),
filename: '[name].bundle.js',
},
module: {
rules: [{
test: /\.ts$/,
exclude: /node_modules/,
use: [
{
loader: 'babel-loader',
options: babelOptions
},
{
loader: 'ts-loader'
}
]
}, {
test: /\.js$/,
exclude: /node_modules/,
use: [
{
loader: 'babel-loader',
options: babelOptions
}
]
}]
},
plugins: [
new AssetsPlugin({ path: path.resolve(__dirname, './dist/assets') }),
new WebpackCleanupPlugin({})
],
}];
如果你使用的是 webpack 2.x 有一个内置插件
你定义了全局变量,然后就可以访问了。
plugins: [
new webpack.ProvidePlugin({
$: "jquery",
jQuery: "jquery",
"window.jQuery": "jquery",
"window.Tether": 'tether',
"Tether": 'tether'
}),
...
]
这是我的完整配置
var webpack = require("webpack");
var ExtractTextPlugin = require("extract-text-webpack-plugin");
var path = require("path")
module.exports = {
entry: "./src/entry-js.js",
devtool: 'source-map',
output: {
path: path.join(__dirname, "/public/dist/js"),
publicPath: "/public/",
filename: 'bundle.js',
chunkFilename: 'chunk.[name].[id].js',
},
module: {
rules: [
{
test: /\.js$/,
loader: "babel-loader",
options: {
presets: ["es2015", "stage-0"]
},
exclude: [
path.resolve(__dirname, "node_modules")
],
},
{
test: /\.css$/,
use: ExtractTextPlugin.extract({
fallback: "style-loader",
use: "css-loader"
})
},
{
test: /\.(scss|sass)$/,
use: ExtractTextPlugin.extract({
fallback: "style-loader",
use: [
"css-loader",
"sass-loader"
]
})
},
{
test: /\.less$/,
use: ExtractTextPlugin.extract({
fallback: "style-loader",
use: [
"css-loader",
"less-loader"
]
})
},
{
test: /\.(png|svg|jpg|gif)$/,
use: [{
loader:"file-loader",
options: {
limit: 500,
name: "../img/[name].[ext]"
}
}]
},
{
test: /\.(woff|woff2|eot|ttf|otf)$/,
use: [{
loader:"file-loader",
options: {
limit: 500,
name: "../fonts/[name].[ext]"
}
}]
}
]
},
plugins: [
new ExtractTextPlugin({
filename: "../css/bundle.css",
disable: false,
allChunks: true
}),
new webpack.ProvidePlugin({
$: "jquery",
jQuery: "jquery",
"window.jQuery": "jquery",
"window.Tether": 'tether',
"Tether": 'tether'
})
]
};
这是我的参赛文件
/********************
* CSS Libraries *
********************/
// normalize v7
import "../node_modules/normalize.css/normalize.css";
// bootstrap v4.alpha-5
import "../node_modules/bootstrap/scss/bootstrap.scss";
/******************
* CSS Custom *
******************/
import "./css/main.css";
import "./sass/main.scss";
/********************
* JS Libraries *
********************/
//Jquery v3.2.1
import '../node_modules/jquery/src/jquery.js';
import Tether from 'tether';
//Bootstrap v4-alpha-5
import "../node_modules/bootstrap/dist/js/bootstrap.min.js";
import "./js/main.js";
注意:这不是理想的情况,但因为我添加了恒定数量的新全局变量,所以我需要制作一个插件来为我捆绑 javascript。
webpack-raw-bundler
这只是将您的代码堆叠在一起以包含在前端。这是我的用法示例:
用法
来自旧的:
<script src="js/jquery.js"></script>
<script src="js/silly.js"></script>
<script>
$(silly()); // Some function in silly.js's global scope
</script>
给新的:
<script src="js/bundle.js"></script>
<script>
$(silly()); // Some function in silly.js's global scope
</script>
正在安装到配置
var RawBundlerPlugin = require('webpack-raw-bundler');
module.exports = {
plugins: [
new RawBundlerPlugin({
excludedFilenames: [/angulartics/],
readEncoding: "utf-8",
includeFilePathComments: false,
bundles: [ "vendor.js", "styles.css" ],
"vendor.js": [
'js/*.js'
],
"styles.css": [
'css/bootstrap.css',
'css/edits.css'
]
})
]
}
一个公平的警告:
这不应该是您的首选解决方案,但我遇到了一个糟糕的案例,这使它成为最简单的选择。使用 expose-loader
和 import
或 window['module'] = require('module.js')
更安全,因为 webpack 就是围绕它构建的。 但是,如果你有些头疼并且只想要一个简单的捆绑器,随意使用这个插件。
我遇到了同样的问题,我找到的最佳解决方案是使用 webpack-concat-plugin。
它的作用:
- 将所有内容合并到一个文件中
- 允许我指定生成的文件名,包括 [cache] 模板以进行缓存清除
- 通过 HtmlWebpackPlugin 将自身添加到结果 html
它唯一没有做的是 not-leaking 全局范围内的所有全局变量。
听起来 OP 正在寻找的是 exports-loader
而不是 expose-loader
。
要公开 模块,请使用 expose-loader
.
要公开 全局变量,请使用 exports-loader
这是明确记录答案的交易之一,但您必须首先了解您要查找的内容并知道其名称。这两个类似的装载机也被赋予了相似的名称,这无济于事。
问题
我觉得这应该比现在更直接。我需要从前端访问我所有的 javascript 库,因为我正在将它集成到一个旧系统中,所以我无法从前端调用 require("bundle.js");
。 捆绑文件全局范围内的所有内容 必须可以从前端页面的全局范围访问,通过 <script>
标签导入它们。
所以我需要改变旧的:
<script src="js/jquery.js"></script>
<script src="js/silly.js"></script>
<script>
$(silly()); // Some function in silly.js's global scope
</script>
给新的:
<script src="js/bundle.js"></script>
<script>
$(silly()); // Some function in silly.js's global scope
</script>
我尝试过的事情
expose-loader: 如果我没有 100 个我不想明确告诉它看起来的全局变量,这将完全有效 为.
ProvidePlugin: 只真正让库看到其他库。我也无法用我当前的设置明确地编写我需要的所有全局变量(不断添加更多)。
我需要的
所以为了更清楚起见,我需要我的 webpack.config.js
看起来像以下选项之一:
// Everything is wrapped in module.exports and other irrelevant things
plugins: [
new StaticLibraryMergerSuperNeatPlugin("js/*.js")
]
// ...
或者:
rules: [
{
test: /\.js$/,
use: [
"neat-merging-cool-loader",
"babel-loader"]
}
]
// ...
我做错了吗?
我缺少明显的解决方案吗?
Tl;博士:
如何从捆绑的 js 文件创建全局变量,当通过 <script src="js/bundle.js"></script>
在前端 html 页面上导入时暴露在全局范围内?
顺便说一句:如果有人是 webpack 的传奇人物并且知道为什么这是一个糟糕的方法,请在下面 post 进行简短的解释,这样我就可以解决问题。
这是我如何在自己的网站上执行此操作的示例。我不确定这是唯一的方法,还是最好的方法,但它干净、简单,而且对我有用。
重要的旁注 - 在 window 上声明事物时使用 window["propName"]
因为当你 运行 webpack -p
它会丑化任何非字符串,因此如果您将其定义为 window.propName
,它可能会更改为类似 s.c
的内容,而您的其余代码不知道它是什么。用括号表示法将其声明为字符串将强制 webpack 保持名称完整,以便您可以从任何地方使用相同的名称访问它。
site.ts(可以是.js,无所谓)
/*************************/
/*** JQUERY + JQUERYUI ***/
/*************************/
/* var declaration for typescript - not needed if not using .ts */
declare var $:JQueryStatic; declare var jQuery:JQueryStatic;
window["$"] = window["jQuery"] = require("jquery");
require("jquery-ui/effects/effect-slide");
require("jquery-ui/widgets/autocomplete");
require("jquery-ui/widgets/button");
require("jquery-ui/widgets/datepicker");
require("jquery-ui/widgets/tooltip");
/*************************/
/* END JQUERY + JQUERYUI */
/*************************/
/***************/
/*** ANGULAR ***/
/***************/
/* var declaration for typescript - not needed if not using .ts */
declare var angular:ng.IAngularStatic;
window["angular"] = require("angular");
require("angular-sanitize");
/***************/
/* END ANGULAR */
/***************/
/************************/
/*** MISC THIRD-PARTY ***/
/************************/
window["moment"] = require("moment");
window["saveAs"] = require("FileSaver").saveAs;
window["JSZip"] = require("jszip");
/************************/
/* END MISC THIRD-PARTY */
/************************/
/* var declaration for typescript - not needed if not using .ts */
declare var globals:Globals;
window["globals"] = require("./globals");
Layout.html(每页加载)
.....
<script src="/dist/scripts/site.bundle.js"></script>
.....
webpack.config.js
var path = require('path');
var resolve = path.resolve;
var AssetsPlugin = require('assets-webpack-plugin');
var WebpackCleanupPlugin = require("webpack-cleanup-plugin");
'use strict';
var babelOptions = {
"presets": [
[
"es2015",
{
"modules": false
}
],
"es2016"
]
};
module.exports = [{
cache: true,
context: resolve('Scripts'),
devtool: "source-map",
entry: {
site: './site.ts',
},
output: {
path: path.resolve(__dirname, './dist/scripts'),
filename: '[name].bundle.js',
},
module: {
rules: [{
test: /\.ts$/,
exclude: /node_modules/,
use: [
{
loader: 'babel-loader',
options: babelOptions
},
{
loader: 'ts-loader'
}
]
}, {
test: /\.js$/,
exclude: /node_modules/,
use: [
{
loader: 'babel-loader',
options: babelOptions
}
]
}]
},
plugins: [
new AssetsPlugin({ path: path.resolve(__dirname, './dist/assets') }),
new WebpackCleanupPlugin({})
],
}];
如果你使用的是 webpack 2.x 有一个内置插件
你定义了全局变量,然后就可以访问了。
plugins: [
new webpack.ProvidePlugin({
$: "jquery",
jQuery: "jquery",
"window.jQuery": "jquery",
"window.Tether": 'tether',
"Tether": 'tether'
}),
...
]
这是我的完整配置
var webpack = require("webpack");
var ExtractTextPlugin = require("extract-text-webpack-plugin");
var path = require("path")
module.exports = {
entry: "./src/entry-js.js",
devtool: 'source-map',
output: {
path: path.join(__dirname, "/public/dist/js"),
publicPath: "/public/",
filename: 'bundle.js',
chunkFilename: 'chunk.[name].[id].js',
},
module: {
rules: [
{
test: /\.js$/,
loader: "babel-loader",
options: {
presets: ["es2015", "stage-0"]
},
exclude: [
path.resolve(__dirname, "node_modules")
],
},
{
test: /\.css$/,
use: ExtractTextPlugin.extract({
fallback: "style-loader",
use: "css-loader"
})
},
{
test: /\.(scss|sass)$/,
use: ExtractTextPlugin.extract({
fallback: "style-loader",
use: [
"css-loader",
"sass-loader"
]
})
},
{
test: /\.less$/,
use: ExtractTextPlugin.extract({
fallback: "style-loader",
use: [
"css-loader",
"less-loader"
]
})
},
{
test: /\.(png|svg|jpg|gif)$/,
use: [{
loader:"file-loader",
options: {
limit: 500,
name: "../img/[name].[ext]"
}
}]
},
{
test: /\.(woff|woff2|eot|ttf|otf)$/,
use: [{
loader:"file-loader",
options: {
limit: 500,
name: "../fonts/[name].[ext]"
}
}]
}
]
},
plugins: [
new ExtractTextPlugin({
filename: "../css/bundle.css",
disable: false,
allChunks: true
}),
new webpack.ProvidePlugin({
$: "jquery",
jQuery: "jquery",
"window.jQuery": "jquery",
"window.Tether": 'tether',
"Tether": 'tether'
})
]
};
这是我的参赛文件
/********************
* CSS Libraries *
********************/
// normalize v7
import "../node_modules/normalize.css/normalize.css";
// bootstrap v4.alpha-5
import "../node_modules/bootstrap/scss/bootstrap.scss";
/******************
* CSS Custom *
******************/
import "./css/main.css";
import "./sass/main.scss";
/********************
* JS Libraries *
********************/
//Jquery v3.2.1
import '../node_modules/jquery/src/jquery.js';
import Tether from 'tether';
//Bootstrap v4-alpha-5
import "../node_modules/bootstrap/dist/js/bootstrap.min.js";
import "./js/main.js";
注意:这不是理想的情况,但因为我添加了恒定数量的新全局变量,所以我需要制作一个插件来为我捆绑 javascript。
webpack-raw-bundler
这只是将您的代码堆叠在一起以包含在前端。这是我的用法示例:
用法
来自旧的:
<script src="js/jquery.js"></script>
<script src="js/silly.js"></script>
<script>
$(silly()); // Some function in silly.js's global scope
</script>
给新的:
<script src="js/bundle.js"></script>
<script>
$(silly()); // Some function in silly.js's global scope
</script>
正在安装到配置
var RawBundlerPlugin = require('webpack-raw-bundler');
module.exports = {
plugins: [
new RawBundlerPlugin({
excludedFilenames: [/angulartics/],
readEncoding: "utf-8",
includeFilePathComments: false,
bundles: [ "vendor.js", "styles.css" ],
"vendor.js": [
'js/*.js'
],
"styles.css": [
'css/bootstrap.css',
'css/edits.css'
]
})
]
}
一个公平的警告:
这不应该是您的首选解决方案,但我遇到了一个糟糕的案例,这使它成为最简单的选择。使用 expose-loader
和 import
或 window['module'] = require('module.js')
更安全,因为 webpack 就是围绕它构建的。 但是,如果你有些头疼并且只想要一个简单的捆绑器,随意使用这个插件。
我遇到了同样的问题,我找到的最佳解决方案是使用 webpack-concat-plugin。
它的作用:
- 将所有内容合并到一个文件中
- 允许我指定生成的文件名,包括 [cache] 模板以进行缓存清除
- 通过 HtmlWebpackPlugin 将自身添加到结果 html
它唯一没有做的是 not-leaking 全局范围内的所有全局变量。
听起来 OP 正在寻找的是 exports-loader
而不是 expose-loader
。
要公开 模块,请使用 expose-loader
.
要公开 全局变量,请使用 exports-loader
这是明确记录答案的交易之一,但您必须首先了解您要查找的内容并知道其名称。这两个类似的装载机也被赋予了相似的名称,这无济于事。