繁体   English   中英

公开通过 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>

我尝试过的事情

  1. 暴露加载器:如果我没有 100 个不想明确告诉它查找的全局变量,这将完全有效。

  2. 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;Dr:如何从捆绑的 js 文件制作全局变量,当通过<script src="js/bundle.js"></script>在前端 html 页面上导入时暴露在全局范围内?

顺便说一句:如果有人是 webpack 传奇并且知道为什么这是一个糟糕的方法,请在下面发布一个简短的解释,以便我可以解决我的生活。

这是我如何在我自己的网站上执行此操作的示例。 我不确定这是否是唯一的方法,甚至是最好的方法,但它干净、简单,而且对我有用。

重要的旁注- 在窗口上声明内容时使用window["propName"]因为当你运行webpack -p它会丑化任何非字符串,所以如果你将它定义为window.propName ,它可以被更改为类似sc而你的其余代码不知道它是什么。 使用方括号将其声明为字符串将强制 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({})
    ],
}];

注意:这不是理想的情况,但是因为我添加了恒定数量的新全局变量,所以我需要制作一个插件来为我捆绑我的 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'
             ]
       })
    ]
 }

一个公平的警告:

这不应该是您的首选解决方案,但我有一个糟糕的案例,使这成为最简单的选择。 使用window['module'] = require('module.js') expose-loaderimportwindow['module'] = require('module.js')更安全,因为 webpack 就是围绕它构建的。 但是,如果您有一些头痛并且只想要一个简单的捆绑器,请随意使用此插件。

听起来OP正在寻找的是exports-loader而不是expose-loader

要公开模块,请使用expose-loader

要公开全局变量,请使用exports-loader

这是明确记录答案的交易之一,但您必须首先了解您要寻找的东西并知道它的名称。 这两个相似的加载器也被赋予了相似的名称,这无济于事。

我遇到了同样的问题,我发现的最佳解决方案是使用webpack-concat-plugin

它的作用:

  • 将所有内容合并到一个文件中
  • 允许我指定生成的文件名,包括 [cache] 模板来执行缓存破坏
  • 通过 HtmlWebpackPlugin 将自身添加到生成的 html

它唯一没有做的就是不将所有全局变量泄漏到全局范围。

如果您使用的是 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";

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM