Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

__webpack_require__(...) is not a function with babel-loader #1223

Closed
mogelbrod opened this issue Jun 10, 2019 · 6 comments
Closed

__webpack_require__(...) is not a function with babel-loader #1223

mogelbrod opened this issue Jun 10, 2019 · 6 comments

Comments

@mogelbrod
Copy link

mogelbrod commented Jun 10, 2019

Expected behaviour

Using babel-loader and html-webpack-plugin shouldn't require any special configuration.

Current behaviour

Webpack throws the following error with a minimal repro using only webpack, babel-loader and html-webpack-plugin:

TypeError: __webpack_require__(...) is not a function
  - index.html:1718 Module../node_modules/webpack/buildin/harmony-module.js

Environment

Node.js v12.1.0
darwin 18.6.0
npm 6.9.0
webpack-issue@1.0.0 .../webpack-issue
└── webpack@4.32.2
webpack-issue@1.0.0 .../webpack-issue
└── html-webpack-plugin@3.2.

Config

const webpack = require('webpack')
const HtmlWebpackPlugin = require('html-webpack-plugin')

module.exports = function(env) {
  return {
    mode: 'development',

    entry: {
      app: './index.js',
    },

    output: {
      path: __dirname + '/dist',
      filename: 'index.js',
      publicPath: '/'
    },

    module: {
      rules: [
        {
          test: /\.js$/,
          loader: 'babel-loader',
        },
      ],
    },

    plugins: [
      new HtmlWebpackPlugin({
        template: 'index.html',
      }),
    ],

    bail: true,

    devServer: {
      contentBase: 'public',
      inline: true,
      port: 3000,
    }
  }
}

Relevant Links

Repository with minimal repro repository

Possibly related:

Workaround

diff --git a/webpack.config.js b/webpack.config.js
index 34e17ce..8bf6b03 100644
--- a/webpack.config.js
+++ b/webpack.config.js
@@ -20,6 +20,9 @@ module.exports = function(env) {
       rules: [
         {
           test: /\.js$/,
+          exclude: [
+            /node_modules\/(webpack|html-webpack-plugin)\//,
+          ],
           loader: 'babel-loader',
         },
       ],
@Akiyamka
Copy link

Akiyamka commented Jun 27, 2019

i have same issue, but with 'useBuiltIns': 'usage' exclude workaround does not help T.T

@jantimon
Copy link
Owner

jantimon commented Jul 7, 2019

Thanks for reporting this bug it looks like it was already reported a while back here without a solution:

webpack/webpack#6544

And you are right it is a duplicate of #637 unfortunately we didn't really understand what is causing the bug.

Thanks to your reproduction repository I was able to do some quick tests and realized that it breaks for html-webpack-plugin 3.2 and 4.x because of a webpack behaviour which I don't understand.

To debug those the bug I used node inspector like the following:

node --inspect-brk node_modules/.bin/webpack

devtool

The bug starts from the html-webpack-plugin function evaluateCompilationResult where it executes the template using a Script.runInContext sandbox.

Inside that sandbox it uses the code generated by the html-webpack-plugin/lib/loader.js which looks like this:

/***/ "./node_modules/html-webpack-plugin/lib/loader.js!./index.html":
/*!*********************************************************************!*\
  !*** ./node_modules/html-webpack-plugin/lib/loader.js!./index.html ***!
  \*********************************************************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {

    var _ = __webpack_require__( /*! !./node_modules/lodash/lodash.js */ "./node_modules/lodash/lodash.js");

    module.exports = function(templateParams) {
        with(templateParams) {
            return (function(data) {
                var __t, __p = '';
                __p += '<!DOCTYPE html>\n<html>\n  <head>\n    <title>Test</title>\n    <meta charset="utf-8">\n    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0" />\n  </head>\n  <body class="loading">\n    <div id="app"></div>\n  </body>\n</html>\n';
                return __p
            })();
        }
    }

    /***/
}),

Now webpack kicks in for __webpack_require__("./node_modules/lodash/lodash.js") and uses the babel-loader as configured in the config.

Webpack loads the node_modules/webpack/buildin/global.js file which tries to provide access to the current global object.

Webpack tries to wrap the harmony-module (webpack/buildin/harmony-module.js) around global.js

webpack/buildin/harmony-module.js

module.exports = function(originalModule) {
	if (!originalModule.webpackPolyfill) {
		var module = Object.create(originalModule);
		// module.parent = undefined by default
		if (!module.children) module.children = [];
		Object.defineProperty(module, "loaded", {
			enumerable: true,
			get: function() {
				return module.l;
			}
		});
		Object.defineProperty(module, "id", {
			enumerable: true,
			get: function() {
				return module.i;
			}
		});
		Object.defineProperty(module, "exports", {
			enumerable: true
		});
		module.webpackPolyfill = 1;
	}
	return module;
};

Now it gets strange:

webpack tries to wrap harmony-module.js around harmony-module.js:

wrap-wrap

Unfortunately I don't understand why this is happening so I won't be able to provide a solution here - maybe @sokra can lead us into the correct direction.

What we could do as a workaround is to try to use the nodejs require instead of __webpack_require__ for lodash - that way we might even execute the template faster but I am not sure if this might introduce new problems.

The workaround (#1239) would be to replace this line

return 'var _ = require(' + loaderUtils.stringifyRequest(this, '!!' + require.resolve('lodash')) + ');' +

with:

return 'var _ = __non_webpack_require__(' + require.resolve('lodash') + ');' +

@mogelbrod
Copy link
Author

Interesting findings! Overall I found it odd that html-webpack-plugin uses webpack to resolve lodash (and any other internal dependencies), so ensuring that it gets loaded via node require instead sounds good. Could this change also prevent lodash from being included in the stats output (as a dependency of html-webpack-plugin entries), which has previously caught me off guard as it's not bundled with anything but merely used to generate the assets.

@sokra
Copy link
Contributor

sokra commented Jul 8, 2019

The problem is documented here: https://babeljs.io/docs/en/options#sourcetype

@sokra
Copy link
Contributor

sokra commented Jul 8, 2019

TL'DR

  • babel inserts imports
  • module becomes a ESM
  • module.exports no longer work

@jantimon
Copy link
Owner

jantimon commented Jul 9, 2019

Thanks @sokra !
I am amazed about what is all in your head 😆

I will merge #1239

@lock lock bot locked as resolved and limited conversation to collaborators Aug 8, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants