webpack: Use CommonsChunkPlugin & `external` config at the same time causes error

I have external module precompiled by webpack in the seperate js, and my project has multiple entry points, I want the webpack.optimize.CommonsChunkPlugin extract common chunks between these entry points, however it seems that it cannot work with externals config in webpack.config.js, and throws an error:

Uncaught ReferenceError: __WEBPACK_EXTERNAL_MODULE_38__ is not defined
(anonymous function) @ external "base":1
__webpack_require__ @ bootstrap 66a520adc59b2bde46c2:564
fn @ bootstrap 66a520adc59b2bde46c2:98
webpackJsonph5_es6_react__name_.68 @ index.scss:8
__webpack_require__ @ bootstrap 66a520adc59b2bde46c2:564
fn @ bootstrap 66a520adc59b2bde46c2:98
webpackJsonph5_es6_react__name_.0 @ index.entry.js:16
__webpack_require__ @ bootstrap 66a520adc59b2bde46c2:564
webpackJsonpCallback @ bootstrap 66a520adc59b2bde46c2:21
(anonymous function) @ index.entry.js:11
webpackUniversalModuleDefinition @ universalModuleDefinition:9
(anonymous function) @ universalModuleDefinition:10

webpack.config.js

module.exports = {
  entry: entryJSMap,
  context: pwd,
  output: {
    path: path.join(pwd, 'build'),
    publicPath: '/build/',
    filename: '[name].entry.js',
    libraryTarget: 'umd',
    library: [pkgConfig.name, '[name]'],
    umdNamedDefine: true
  },
  module: {
    loaders: [
      ...
    ]
  },
  devtool: '#source-map',
  plugins: [
    new webpack.optimize.CommonsChunkPlugin({
      name: "commons",
      // (the commons chunk name)

      filename: "commons.js",
      // (the filename of the commons chunk)

      // minChunks: 3,
      // (Modules must be shared between 3 entries)

      //chunks: Object.keys(entryJSMap).concat(['base'])
      // (Only use these entries)
    }),
    new webpack.HotModuleReplacementPlugin()
  ],
  resolve: {
    root: [
      path.resolve('./node_modules'),
      path.resolve('./src/widgets')
    ]
  },
  externals: ["base"]
};

entry 1 js

"use strict";
import {React, ReactDOM} from 'base';

import PageHeader from '../../mods/header/index';

ReactDOM.render(<PageHeader subTitle="Home page here!"/>, document.getElementById('J_Page'));

entry 1 html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Home</title>
</head>
<body>
    <div class="page-content" id="J_Page"></div>
    <script src="../../widgets/base/seed-react.js"></script>
    <script src="../../commons.js"></script>
    <script src="./index.entry.js"></script>
</body>
</html>

entry 2 js

"use strict";
import {React, ReactDOM} from 'base';

import PageHeader from '../../mods/header/index';

ReactDOM.render(<PageHeader subTitle="Detail page here!"/>, document.getElementById('J_Page'));

entry 2 html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Detail</title>
</head>
<body>
    <div class="page-content" id="J_Page"></div>
    <script src="../../widgets/base/seed-react.js"></script>
    <script src="../../commons.js"></script>
    <script src="./index.entry.js"></script>
</body>
</html>

…/…/widgets/base/seed-react.js

(function webpackUniversalModuleDefinition(root, factory) {
    if(typeof exports === 'object' && typeof module === 'object')
        module.exports = factory();
    else if(typeof define === 'function' && define.amd)
        define("base", [], factory);
    else if(typeof exports === 'object')
        exports["base"] = factory();
    else
        root["base"] = factory();
})(this, function() {
return /******/ (function(modules) { // webpackBootstrap
/******/    // The module cache
/******/    var installedModules = {};
/******/
/******/    // 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] = {
/******/            exports: {},
/******/            id: moduleId,
/******/            loaded: false
/******/        };
/******/
/******/        // Execute the module function
/******/        modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/
/******/        // Flag the module as loaded
/******/        module.loaded = true;
/******/
/******/        // Return the exports of the module
/******/        return module.exports;
/******/    }
/******/
/******/
/******/    // expose the modules object (__webpack_modules__)
/******/    __webpack_require__.m = modules;
/******/
/******/    // expose the module cache
/******/    __webpack_require__.c = installedModules;
/******/
/******/    // __webpack_public_path__
/******/    __webpack_require__.p = "/build/";
/******/
/******/    // Load entry module and return exports
/******/    return __webpack_require__(0);
/******/ })
/************************************************************************/
/******/ ([
/* 0 */
/***/ function(module, exports, __webpack_require__) {}...
])
});
;

Looking forward from your explanation and solution, thank you!

About this issue

  • Original URL
  • State: closed
  • Created 8 years ago
  • Comments: 17 (4 by maintainers)

Commits related to this issue

Most upvoted comments

I got this problem when using require.ensure and specifying externals: [‘react’]

why no people 鸟 you

I still have this issue with Webpack 2.1.0.beta-27

Hello,

I encoutered this problem when using externals and require.ensure, and managed to find the issue. I was using require.ensure to split my app code in named-chunks, and noticed that only the entry chunk/file had the “webpackUniversalModuleDefinition” at the beginning.

After some research, I managed to make it work. In UmdMainTemplatePlugin.js, I changed compilation.templatesPlugin("render-with-entry" to compilation.templatesPlugin("render", so the universal definitions are added.

Since I am unsure about the side effects of this, I prefered ot post here instead of doing a PR.

@sokra I hope it can help