Note: Webpack by default is a module bundler, wrapping each javascript file as a module (cannot be accessed globally by default, resolve modules through import or require statement).
Do refer to Webpack: Merge Multiple Javascript Into Single File.
This article shall focus on how to enable the merged javascripts to be accessible in global scope, especially from HTML which include the javascript.
expose-loader
You can combine javascripts using the standard way, but expose the javascript into global scope using expose-loader.
npm install --save-dev expose-loadernpm install --save-dev jquery
Edit webpack.config.js
. We shall merge npm jquery
, src/util.js
and src/index.js
into dist/bundle.js
.
const path = require('path');module.exports = { entry: { 'bundle.js': [ "jquery", path.resolve(__dirname, 'src/util.js'), path.resolve(__dirname, 'src/index.js') ] }, output: { filename: '[name]', path: path.resolve(__dirname, 'dist'), }, module: { rules: [ /* // somehow the following expose-loader declaration doesn't work // https://github.com/webpack-contrib/expose-loader/issues/51 { test: require.resolve('jquery'), use: [{ loader: 'expose-loader', options: '$' }] } */ ], }
Edit src/utils.js
. Attributes which is to be exposed globally must be declared in module.exports.
var today = "Monday";module.exports = { getName: function () { return "Desmond Lua"; }, today: today};
Edit src/index.js
. Add the following code to expose jquery
as $
in global scope, util.js
as util
.
// expose jquery globally as $require("expose-loader?$!jquery");// epose util.js globally as utilrequire("expose-loader?util!./util.js");
Build.
./node_modules/.bin/webpack
Edit dist/index.html
to test if $
and util
is explosed in global scope. Preview dist/index.html
in browser.
<html> <head> <title>Hello</title> </head> <body> <script src="bundle.js"></script> <script> // test if $jquery and util accessible in global scope $("body").text(util.getName() + ", today is " + util.today); </script> <div id="output"></name> </body></html>
Project structure.
├── dist
│ ├── bundle.js
│ ├── index.html
├── src
│ ├── index.js
│ └── util.js
└── webpack.config.js
Manually expose to global scope
You can also manually expose modules into global scope without using expose-loader.
Edit src/index.js
.
var jquery = require('jquery');import util from './util.js';window.$ = jquery;window.util = util;
ProvidePlugin
ProvidePlugin can automatically load modules instead of having to import or require them everywhere. This global scope only apply within the module bundle, not accessible from HTML file.
Edit webpack.config.js
.
const path = require('path');const webpack = require('webpack');module.exports = { entry: { 'bundle.js': [ "jquery", path.resolve(__dirname, 'src/util.js'), path.resolve(__dirname, 'src/index.js') ] }, output: { filename: '[name]', path: path.resolve(__dirname, 'dist'), }, plugins: [ new webpack.ProvidePlugin({ $: "jquery", util: path.resolve(__dirname, 'src/util.js') }) ]};
Edit src/index.js
.
// $ and util is automatically require/import using ProvidePluginwindow.$ = $;window.util = util;
output.library
You can use output.library to export your module bundle as variable.
Edit webpack.config.js
. We name our module bundle library as bundle.
const path = require('path');module.exports = { entry: { 'bundle.js': [ "jquery", path.resolve(__dirname, 'src/util.js'), path.resolve(__dirname, 'src/index.js') ] }, output: { filename: '[name]', path: path.resolve(__dirname, 'dist'), libraryTarget: 'var', library: 'bundle' }};
Edit src/index.js
.
var jquery = require('jquery');var util = require('./util.js');module.exports = { $: jquery, util: util};
Edit dist/index.html
.
<html> <head> <title>Hello</title> </head> <body> <script src="bundle.js"></script> <script> bundle.$("body").text(bundle.util.getName() + ", today is " + bundle.util.today); </script> <div id="output"></name> </body></html>
webpack-merge-and-include-globally
There easiet way is to utlize webpack-merge-and-include-globally plugin, which will generate pure javascript file without module bundling. It should be able to combine any file without modification, including .css
and .js
.
Sadly, this plugin doesn't support webpack optimization such as minify.
npm install --save-dev webpack-merge-and-include-globally
Edit webpack.config.js
.
const path = require('path');const MergeIntoSingleFilePlugin = require('webpack-merge-and-include-globally');module.exports = { entry: './src/index.js', output: { filename: '[name]', path: path.resolve(__dirname, 'dist'), }, plugins: [ new MergeIntoSingleFilePlugin({ "bundle.js": [ path.resolve(__dirname, 'src/util.js'), path.resolve(__dirname, 'src/index.js') ], "bundle.css": [ path.resolve(__dirname, 'src/css/main.css'), path.resolve(__dirname, 'src/css/local.css') ] }) ]};
Build.
./node_modules/.bin/webpack# production parameter doesn't have minify effect on webpack-merge-and-include-globally# ./node_modules/.bin/webpack -p