Expose javascript globals bundled via webpack

后端 未结 5 2027
鱼传尺愫
鱼传尺愫 2020-12-09 03:54

The Problem

I feel like this should be more straightforward than it is. I need to access all my javascript libraries from the frontend and because I\'m integrating

相关标签:
5条回答
  • 2020-12-09 04:15

    If you are using webpack 2.x there is a built-in plugin

    You define the global variable and then it can be accessed.

        plugins: [
            new webpack.ProvidePlugin({
                $: "jquery",
                jQuery: "jquery",
                "window.jQuery": "jquery",
                "window.Tether": 'tether',
                "Tether": 'tether'
            }),
            ...
        ]
    

    here is my full config

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

    Here is my entry file

    /********************
     *   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 讨论(0)
  • 2020-12-09 04:21

    Here's an example of how I do it in my own site. I'm not sure if it's the only way, or even the best way, but it's clean, simple, and it works for me.

    Important side note - Use window["propName"] when declaring things on the window because when you run webpack -p it will uglify any non-strings, so if you define it as window.propName, it can get changed to something like s.c and the rest of your code does not know what it is. Declaring it with bracket notation as a string will force webpack to keep the name intact so you can access it from anywhere with the same name.

    site.ts (can be .js, doesn't matter)

    /*************************/
    /*** 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 (loaded on every page)

    .....
    <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({})
        ],
    }];
    
    0 讨论(0)
  • 2020-12-09 04:21

    I've had the same problem and the best solution I've found is using webpack-concat-plugin.

    What it does:

    • Concats everything to a single file
    • Allows me to specify the resulting file name, including [cache] template to do cache busting
    • Adds itself via HtmlWebpackPlugin to the resulting html

    The only thing it doesn't do is not-leaking all the globals to the global scope.

    0 讨论(0)
  • 2020-12-09 04:23

    Note: This is not the ideal scenario but because I have a constant amount of new globals being added, I needed to make a plugin to bundle my javascript for me.

    webpack-raw-bundler

    This simply stacks your code together to be included on the frontend. Here is my usage example:

    Usage

    From the old:

    <script src="js/jquery.js"></script>
    <script src="js/silly.js"></script>
    <script>
        $(silly()); // Some function in silly.js's global scope
    </script>
    

    To the new:

    <script src="js/bundle.js"></script>
    <script>
        $(silly()); // Some function in silly.js's global scope
    </script>
    

    Installing to the config

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

    A Fair Warning:

    This should not be your go-to solution, but I had a bad case that made this the easiest option. Using expose-loader and import or window['module'] = require('module.js') is much safer as that is what webpack was built around. However, if you are having some headaches and just want a simple bundler, feel free to use this plugin.

    0 讨论(0)
  • 2020-12-09 04:39

    It sounds like what the OP was looking for was the exports-loader instead of the the expose-loader.

    To expose modules, use the expose-loader.

    To expose global variables, use the exports-loader

    This is one of those deals where the answer is clearly documented, but you had to be aware of the thing you're looking for first and know its name. It doesn't help matters that these two similar loaders were also given similar names.

    0 讨论(0)
提交回复
热议问题