web-dev-qa-db-ja.com

Webpackを介してバンドルされたJavaScriptグローバルを公開する

問題

これはもっと簡単なはずだと思います。フロントエンドからすべての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. expose-loader:これは、探すように明示的に伝えたくない100個のグローバル変数がなかった場合に完全に機能します。

  2. ProvidePlugin:実際にライブラリに他のライブラリを表示させるだけです。また、現在のセットアップで必要なすべてのグローバルを明示的に書き込むことはできません(Moreは常に追加されています)。

必要なもの

したがって、より明確にするために、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の伝説であり、これが悪いアプローチである理由を知っている場合は、簡単な説明を添えて以下に投稿して、私の人生を直してください。

17
Anselm

注:これは理想的なシナリオではありませんが、新しいグローバルが一定量追加されているため、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が構築されているため、はるかに安全です。ただし、いくつかの問題があり、シンプルなバンドラー。このプラグインを自由に使用してください。

2
Anselm

これが私が自分のサイトでそれを行う方法の例です。それが唯一の方法であるのか、それとも最良の方法であるのかさえわかりませんが、それはクリーンでシンプルであり、私にとってはうまくいきます。

重要な補足-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({})
    ],
}];
10
mhodges

私は同じ問題を抱えており、私が見つけた最良の解決策はwebpack-concat-pluginを使用することです。

それがすること:

  • すべてを単一のファイルに連結します
  • キャッシュの無効化を行う[キャッシュ]テンプレートを含む、結果のファイル名を指定できます
  • 結果のHTMLにHtmlWebpackPluginを介して自分自身を追加します

それがしない唯一のことは、すべてのグローバルをグローバルスコープに漏らさないことです。

1
VitalyB

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";
0
Christian4423

OPが探していたのはexports-loaderの代わりにexpose-loader

モジュールを公開するには、 expose-loader

グローバル変数を公開するには、 exports-loader

これは、答えが明確に文書化されている取引の1つですが、最初に探しているものを認識し、その名前を知る必要がありました。これら2つの同様のローダーに同様の名前が付けられていることは問題になりません。

0
Paul Williams