Skip to content

Instantly share code, notes, and snippets.

@jakepusateri
Last active April 13, 2017 04:23
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jakepusateri/51074ab06fd96b96dbf677bcb9165162 to your computer and use it in GitHub Desktop.
Save jakepusateri/51074ab06fd96b96dbf677bcb9165162 to your computer and use it in GitHub Desktop.
webpack-bug-demo
node_modules/
npm install
npm run build
npm run serve
console.log('a-out.js executed');
webpackJsonp([1],[
/* 0 */,
/* 1 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
Object.defineProperty(__webpack_exports__, "__esModule", { value: true });
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__shared__ = __webpack_require__(0);
__webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__shared__["a" /* default */])();
console.log('a init');
/***/ })
],[1]);
console.log('b-out.js executed');
webpackJsonp([0],{
/***/ 2:
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
Object.defineProperty(__webpack_exports__, "__esModule", { value: true });
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__shared__ = __webpack_require__(0);
__webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__shared__["a" /* default */])();
console.log('b init');
/***/ })
},[2]);
console.log('commons.js executed');
/******/ (function(modules) { // webpackBootstrap
/******/ // install a JSONP callback for chunk loading
/******/ var parentJsonpFunction = window["webpackJsonp"];
/******/ window["webpackJsonp"] = function webpackJsonpCallback(chunkIds, moreModules, executeModules) {
/******/ // add "moreModules" to the modules object,
/******/ // then flag all "chunkIds" as loaded and fire callback
/******/ var moduleId, chunkId, i = 0, resolves = [], result;
/******/ for(;i < chunkIds.length; i++) {
/******/ chunkId = chunkIds[i];
/******/ if(installedChunks[chunkId])
/******/ resolves.push(installedChunks[chunkId][0]);
/******/ installedChunks[chunkId] = 0;
/******/ }
/******/ for(moduleId in moreModules) {
/******/ if(Object.prototype.hasOwnProperty.call(moreModules, moduleId)) {
/******/ modules[moduleId] = moreModules[moduleId];
/******/ }
/******/ }
/******/ if(parentJsonpFunction) parentJsonpFunction(chunkIds, moreModules, executeModules);
/******/ while(resolves.length)
/******/ resolves.shift()();
/******/ if(executeModules) {
/******/ for(i=0; i < executeModules.length; i++) {
/******/ result = __webpack_require__(__webpack_require__.s = executeModules[i]);
/******/ }
/******/ }
/******/ return result;
/******/ };
/******/
/******/ // The module cache
/******/ var installedModules = {};
/******/
/******/ // objects to store loaded and loading chunks
/******/ var installedChunks = {
/******/ 2: 0
/******/ };
/******/
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/
/******/ // Check if module is in cache
/******/ if(installedModules[moduleId])
/******/ return installedModules[moduleId].exports;
/******/
/******/ // Create a new module (and put it into the cache)
/******/ var module = installedModules[moduleId] = {
/******/ i: moduleId,
/******/ l: false,
/******/ exports: {}
/******/ };
/******/
/******/ // Execute the module function
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/
/******/ // Flag the module as loaded
/******/ module.l = true;
/******/
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
/******/
/******/ // This file contains only the entry chunk.
/******/ // The chunk loading function for additional chunks
/******/ __webpack_require__.e = function requireEnsure(chunkId) {
/******/ if(installedChunks[chunkId] === 0)
/******/ return Promise.resolve();
/******/
/******/ // a Promise means "currently loading".
/******/ if(installedChunks[chunkId]) {
/******/ return installedChunks[chunkId][2];
/******/ }
/******/
/******/ // setup Promise in chunk cache
/******/ var promise = new Promise(function(resolve, reject) {
/******/ installedChunks[chunkId] = [resolve, reject];
/******/ });
/******/ installedChunks[chunkId][2] = promise;
/******/
/******/ // start chunk loading
/******/ var head = document.getElementsByTagName('head')[0];
/******/ var script = document.createElement('script');
/******/ script.type = 'text/javascript';
/******/ script.charset = 'utf-8';
/******/ script.async = true;
/******/ script.timeout = 120000;
/******/
/******/ if (__webpack_require__.nc) {
/******/ script.setAttribute("nonce", __webpack_require__.nc);
/******/ }
/******/ script.src = __webpack_require__.p + "" + chunkId + "-out.js";
/******/ var timeout = setTimeout(onScriptComplete, 120000);
/******/ script.onerror = script.onload = onScriptComplete;
/******/ function onScriptComplete() {
/******/ // avoid mem leaks in IE.
/******/ script.onerror = script.onload = null;
/******/ clearTimeout(timeout);
/******/ var chunk = installedChunks[chunkId];
/******/ if(chunk !== 0) {
/******/ if(chunk) chunk[1](new Error('Loading chunk ' + chunkId + ' failed.'));
/******/ installedChunks[chunkId] = undefined;
/******/ }
/******/ };
/******/ head.appendChild(script);
/******/
/******/ return promise;
/******/ };
/******/
/******/ // expose the modules object (__webpack_modules__)
/******/ __webpack_require__.m = modules;
/******/
/******/ // expose the module cache
/******/ __webpack_require__.c = installedModules;
/******/
/******/ // identity function for calling harmony imports with the correct context
/******/ __webpack_require__.i = function(value) { return value; };
/******/
/******/ // define getter function for harmony exports
/******/ __webpack_require__.d = function(exports, name, getter) {
/******/ if(!__webpack_require__.o(exports, name)) {
/******/ Object.defineProperty(exports, name, {
/******/ configurable: false,
/******/ enumerable: true,
/******/ get: getter
/******/ });
/******/ }
/******/ };
/******/
/******/ // getDefaultExport function for compatibility with non-harmony modules
/******/ __webpack_require__.n = function(module) {
/******/ var getter = module && module.__esModule ?
/******/ function getDefault() { return module['default']; } :
/******/ function getModuleExports() { return module; };
/******/ __webpack_require__.d(getter, 'a', getter);
/******/ return getter;
/******/ };
/******/
/******/ // Object.prototype.hasOwnProperty.call
/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
/******/
/******/ // __webpack_public_path__
/******/ __webpack_require__.p = "";
/******/
/******/ // on error function for async loading
/******/ __webpack_require__.oe = function(err) { console.error(err); throw err; };
/******/ })
/************************************************************************/
/******/ ([
/* 0 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
/* harmony export (immutable) */ __webpack_exports__["a"] = share;
function share() {
return 1;
}
/***/ })
/******/ ]);
import share from './shared';
share();
console.log('a init');
import share from './shared';
share();
console.log('b init');
<html lang="en">
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<title>Demo</title>
</head>
<body>
<h1>Demo</h1>
<script>
function insertScript(url) {
var script = document.createElement('script');
script.type = 'text/javascript';
script.src = url;
document.head.appendChild(script);
}
function loadA() {
loadCommons();
insertScript('/a-out.js');
}
function loadB() {
loadCommons();
insertScript('/b-out.js');
}
var isCommonsLoaded;
function loadCommons() {
if (isCommonsLoaded) {
return;
}
insertScript('/commons.js');
isCommonsLoaded = true;
}
</script>
<button onClick="loadA()">Load A</button>
<button onClick="loadB()">Load B</button>
<p>
Check out the console. Each time the buttons are clicked, another script tag gets added.
This runs the code inside the script. As entry modules, each time A or B are loaded,
they entry modules should be re-run, and log their init. This is not what happens.
Instead, they only run on the first click/load. After which, they are in the module cache.
</p>
<p>
This behavior is different than webpack 1 and I believe incorrect. Entry modules should
be re-run when the script is reloaded as they often have important side effects, such as
rendering a React component.
</p>
</body>
</html>
{
"name": "webpack2-execute-modules-bug",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build": "webpack",
"serve": "http-server"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"http-server": "^0.9.0",
"webpack": "^2.3.3",
"webpack-sources": "^0.2.3"
}
}
export default function share() {
return 1;
}
const webpack = require('webpack');
const ConcatSource = require("webpack-sources").ConcatSource;
// Make each file console.log its own name when executed
class NameAnnouncerPlugin {
apply(compiler) {
compiler.plugin("compilation", (compilation) => {
compilation.plugin("optimize-chunk-assets", (chunks, callback) => {
chunks.forEach((chunk) => {
chunk.files
.forEach((file) =>
compilation.assets[file] = new ConcatSource(
`console.log('${file} executed');`, "\n", compilation.assets[file]
)
);
});
callback();
});
});
}
}
module.exports = {
output: {
filename: "[name]-out.js"
},
entry: {
a: './entry-a.js',
b: './entry-b.js'
},
plugins: [
new webpack.optimize.CommonsChunkPlugin({
name: 'commons',
filename: 'commons.js',
chunks: ['a', 'b']
}),
new NameAnnouncerPlugin()
]
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment