title: How should I invoke webpack to bundle bazel's ts_library output
body: <p>I'm trying to build a React JS app from Typescript sources, built with Bazel and using Webpack as the bundler. rules_nodejs includes <a href="https://github.com/bazelbuild/rules_nodejs/tree/stable/examples/react_webpack" rel="nofollow noreferrer">examples/react_webpack</a>, which shows how to do it using <code>ts_project</code>, but I need to build it using <code>ts_library</code> because <code>ts_project</code> doesn't seem to do well with generated TS files (in my case protobuf TS files).</p>
  <p>How do I get <code>ts_library</code> to play nice with Webpack (or vice versa)?</p>
  <p><a href="https://github.com/simmonmt/rules_nodejs/commit/c2f1fdb279b7832c4577b8142e4d621445198451" rel="nofollow noreferrer">Here</a> is my attempt to adapt examples/react_webpack to use <code>ts_library</code> instead of <code>ts_project</code>. It uses Webpack 4 because that's what the example uses, and I wanted to minimize change. For completeness, I also have <a href="https://github.com/simmonmt/rules_nodejs/commit/086e314b74133dafaab07ce1cbac2e9074c07bc3" rel="nofollow noreferrer">this commit</a> which reproduces the change with Webpack 5, though it's my first time using Webpack 5 so it's possible that I introduced additional problems with the migration.</p>
  <p>When I run <code>bazel run server</code> with the Webpack 4 commit, then load the resulting page in Chrome, I get this error on console:</p>
  <pre><code>app.bundle.js:6 Uncaught Error: Cannot find module 'react'
      at n (app.bundle.js:6)
      at app.bundle.js:6
      at app.bundle.js:6
      at Object.&lt;anonymous&gt; (app.bundle.js:6)
      at n (app.bundle.js:1)
      at app.bundle.js:1
      at app.bundle.js:1
  </code></pre>
  <p>Webpack 5 emits a similar error, though slightly more informative(?):</p>
  <pre><code>_sync:2 Uncaught Error: Cannot find module 'react'
      at webpackEmptyContext (_sync:2)
      at eval (index.tsx:7)
      at eval (index.js:3)
      at eval (index.js:12)
      at Object../bazel-out/k8-fastbuild/bin/index.js (main.js:18)
      at __webpack_require__ (main.js:172)
      at main.js:188
      at main.js:189
  </code></pre>
  <p>In both cases, I hit a webpack require for <code>./bazel-out/k8-fastbuild/bin/index.js</code>, which is what I've designated as my entry point (not sure if that's the right path to have specified as the entry point). This leads me into the <code>index.js</code> AMD(?) module, which then requires <code>./bazel-out/k8-fastbuild/bin sync recursive</code>. That requirement seems to lead directly to the error:</p>
  <pre><code>/***/ &quot;./bazel-out/k8-fastbuild/bin sync recursive&quot;:
  /*!******************************************!*\
    !*** ./bazel-out/k8-fastbuild/bin/ sync ***!
    \******************************************/
  /***/ ((module) =&gt; {
  
  eval(&quot;function webpackEmptyContext(req) {\n\tvar e = new Error(\&quot;Cannot find module '\&quot; + req + \&quot;'\&quot;);\n\te.code = 'MODULE_NOT_FOUND';\n\tthrow e;\n}\nwebpackEmptyContext.keys = () =&gt; [];\nwebpackEmptyContext.resolve = webpackEmptyContext;\nwebpackEmptyContext.id = \&quot;./bazel-out/k8-fastbuild/bin sync recursive\&quot;;\nmodule.exports = webpackEmptyContext;\n\n//# sourceURL=webpack:///./bazel-out/k8-fastbuild/bin/_sync?&quot;);
  </code></pre>
  <p>One other thing I noticed:</p>
  <p>The rules_nodejs examples/react_webpack example, using <code>ts_project</code>, compiles <code>index.tsx</code> like this:</p>
  <pre><code>&quot;use strict&quot;;
  exports.__esModule = true;
  var React = require(&quot;react&quot;);
  var ReactDOM = require(&quot;react-dom&quot;);
  var styles = require(&quot;./styles.css&quot;);
  ReactDOM.render(React.createElement(&quot;h1&quot;, { className: styles.h1 }, &quot;Hello, world!&quot;), document.getElementById(&quot;root&quot;));
  s
  </code></pre>
  <p>I think that's a script?</p>
  <p><code>ts_library</code> compiles it like this, which I think is a module?</p>
  <pre><code>(function (factory) {
      if (typeof module === &quot;object&quot; &amp;&amp; typeof module.exports === &quot;object&quot;) {
          var v = factory(require, exports);
          if (v !== undefined) module.exports = v;
      }
      else if (typeof define === &quot;function&quot; &amp;&amp; define.amd) {
          define(&quot;react_webpack/index&quot;, [&quot;require&quot;, &quot;exports&quot;, &quot;react&quot;, &quot;react-dom&quot;], factory);
      }
  })(function (require, exports) {
      &quot;use strict&quot;;
      Object.defineProperty(exports, &quot;__esModule&quot;, { value: true });
      const React = require(&quot;react&quot;);
      const ReactDOM = require(&quot;react-dom&quot;);
      ReactDOM.render(React.createElement(&quot;h1&quot;, null, &quot;Hello, world!&quot;), document.getElementById(&quot;root&quot;));
  });
  //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9pbmRleC50c3giXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7SUFBQSwrQkFBK0I7SUFDL0Isc0NBQXNDO0lBRXRDLFFBQVEsQ0FBQyxNQUFNLENBQ2IsZ0RBQXNCLEVBQ3RCLFFBQVEsQ0FBQyxjQUFjLENBQUMsTUFBTSxDQUFDLENBQ2hDLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgKiBhcyBSZWFjdCBmcm9tIFwicmVhY3RcIjtcbmltcG9ydCAqIGFzIFJlYWN0RE9NIGZyb20gXCJyZWFjdC1kb21cIjtcblxuUmVhY3RET00ucmVuZGVyKFxuICA8aDE+SGVsbG8sIHdvcmxkITwvaDE+LFxuICBkb2N1bWVudC5nZXRFbGVtZW50QnlJZChcInJvb3RcIilcbik7XG4iXX0=
  </code></pre>
  <p>Is that difference the root of the problem? Should I be trying to figure out why/how <code>ts_project</code> uses the simpler form, then convince <code>ts_library</code> to do the same thing? Or is it better to tell Webpack to bundle the <code>ts_library</code> outputs as-is? If the latter, how?</p>
  <p><strong>EDIT:</strong> The <code>ts_library</code> rule seems to be using a tsconfig of its own devising that sets <code>compilerOptions.module</code> to <code>umd</code>. Setting the same option in the <code>ts_project</code> version causes <code>index.js</code> to grow all the factory goo shown above.</p>