<p dir="auto"><strong>Do you want to request a <em>feature</em> or report a <em>bug</em>?</strong><br>
Feature Reqeust</p>
<p dir="auto"><strong>If this is a feature request, what is motivation or use case for changing the behavior?</strong></p>
<h3 dir="auto">The Problem</h3>
<p dir="auto">In <a href="https://github.com/vuejs/vue-loader">vue-loader</a>, we process Vue single file components that can contain multiple language blocks:</p>
<div class="highlight highlight-text-html-vue notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="&lt;template&gt;/* ... */&lt;/template&gt;
&lt;script&gt;/* ... */&lt;/script&gt;
&lt;style&gt;/* ... */&lt;/style&gt;"><pre class="notranslate">&lt;<span class="pl-ent">template</span>&gt;/* ... */&lt;/<span class="pl-ent">template</span>&gt;
<span class="pl-s1">&lt;<span class="pl-ent">script</span>&gt;<span class="pl-c"><span class="pl-c">/*</span> ... <span class="pl-c">*/</span></span>&lt;/<span class="pl-ent">script</span>&gt;</span>
<span class="pl-s1">&lt;<span class="pl-ent">style</span>&gt;<span class="pl-c"><span class="pl-c">/*</span> ... <span class="pl-c">*/</span></span>&lt;/<span class="pl-ent">style</span>&gt;</span></pre></div>
<p dir="auto">Each of these blocks need to be delegated to other webpack loaders for potential pre-processing. The way it currently works is by overloading the same source module with different inline loader chains:</p>
<div class="highlight highlight-source-js notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="// (output from vue-loader)
import template from '!!vue-template-compiler!selector?part=template!self.vue'
import script from '!!babel-loader?babelOptions!selector?part=script!self.vue'
import style from '!!style-loader!css-loader!selector?part=style!self.vue'"><pre class="notranslate"><span class="pl-c">// (output from vue-loader)</span>
<span class="pl-k">import</span> <span class="pl-s1">template</span> <span class="pl-k">from</span> <span class="pl-s">'!!vue-template-compiler!selector?part=template!self.vue'</span>
<span class="pl-k">import</span> <span class="pl-s1">script</span> <span class="pl-k">from</span> <span class="pl-s">'!!babel-loader?babelOptions!selector?part=script!self.vue'</span>
<span class="pl-k">import</span> <span class="pl-s1">style</span> <span class="pl-k">from</span> <span class="pl-s">'!!style-loader!css-loader!selector?part=style!self.vue'</span></pre></div>
<p dir="auto">This does work and we've been using it for quite a long time. However, this leads to a number of problems:</p>
<ul dir="auto">
<li>
<p dir="auto">Because all loader options must be inlined, it's impossible to use non-serializable option values.</p>
</li>
<li>
<p dir="auto">Because the requests all end in <code class="notranslate">*.vue</code>, we cannot rely on the configured rules in the main webpack config. The user has to duplicate the same config in both <code class="notranslate">module.rules</code> and vue-loader's own <code class="notranslate">loaders</code> option, or we have to somehow infer it correctly.</p>
<p dir="auto">This can be circumvented if the pre-processor supports a fs-based config file, e.g. <code class="notranslate">.babelrc</code> or <code class="notranslate">.postcssrc</code>, but in some cases the user for some reason cannot use a config file, or the loader in question simply does not support config files.</p>
</li>
<li>
<p dir="auto">If the user chains another loader before <code class="notranslate">vue-loader</code>, we have to respect that too. This causes the chained loader to be invoked many times (1 extra call for every language block in a vue file).</p>
</li>
<li>
<p dir="auto">(cosmetic) these inline requests result in extremely long module names and makes error and stats output difficult to read.</p>
</li>
</ul>
<h3 dir="auto">Proposed API</h3>
<p dir="auto"><a class="user-mention notranslate" data-hovercard-type="user" data-hovercard-url="/users/TheLarkInn/hovercard" data-octo-click="hovercard-link-click" data-octo-dimensions="link_type:self" href="https://github.com/TheLarkInn">@TheLarkInn</a> had an experimental idea of a <a href="https://github.com/TheLarkInn/virtual-dependency-loader">virtual-dependency-loader</a> which is almost what we want. Except it doesn't seem to work as intended. I tested it with a virtual dependency with a filename ending in <code class="notranslate">.js</code>, and a configured <code class="notranslate">babel-loader</code> does not apply to the loaded virtual module.</p>
<p dir="auto">I propose a new loader context API <code class="notranslate">loadVirtualModule</code> that is similar to <code class="notranslate">loadModule</code>:</p>
<div class="highlight highlight-source-js notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="// in a loader
module.exports = function (source) {
  const cb = this.async()

  const descriptor = vueCompiler.parseComponent(source)

  this.loadVirtualModule({
    code: descriptor.script.content,
    map: descriptor.script.map,
    filename: './does-not-exist.js'
  }, (err, code, map) =&gt; {
    // the script part of the source, processed with all matching loaders
    // for does-not-exist.js
  })

  // even better if it returns Promise
  Promise.all([
    this.loadVirtualModule({ ... }), // script
    this.loadVirtualModule({ ... }),  // template
    this.loadVirtualModule({ ... }),  // style
  ]).then(parts =&gt; {
    const { code, map } = vueCompiler.assemble(parts)
    cb(null, code, map)
  })
}"><pre class="notranslate"><span class="pl-c">// in a loader</span>
<span class="pl-smi">module</span><span class="pl-kos">.</span><span class="pl-en">exports</span> <span class="pl-c1">=</span> <span class="pl-k">function</span> <span class="pl-kos">(</span><span class="pl-s1">source</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
  <span class="pl-k">const</span> <span class="pl-s1">cb</span> <span class="pl-c1">=</span> <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-en">async</span><span class="pl-kos">(</span><span class="pl-kos">)</span>

  <span class="pl-k">const</span> <span class="pl-s1">descriptor</span> <span class="pl-c1">=</span> <span class="pl-s1">vueCompiler</span><span class="pl-kos">.</span><span class="pl-en">parseComponent</span><span class="pl-kos">(</span><span class="pl-s1">source</span><span class="pl-kos">)</span>

  <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-en">loadVirtualModule</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
    <span class="pl-c1">code</span>: <span class="pl-s1">descriptor</span><span class="pl-kos">.</span><span class="pl-c1">script</span><span class="pl-kos">.</span><span class="pl-c1">content</span><span class="pl-kos">,</span>
    <span class="pl-c1">map</span>: <span class="pl-s1">descriptor</span><span class="pl-kos">.</span><span class="pl-c1">script</span><span class="pl-kos">.</span><span class="pl-c1">map</span><span class="pl-kos">,</span>
    <span class="pl-c1">filename</span>: <span class="pl-s">'./does-not-exist.js'</span>
  <span class="pl-kos">}</span><span class="pl-kos">,</span> <span class="pl-kos">(</span><span class="pl-s1">err</span><span class="pl-kos">,</span> <span class="pl-s1">code</span><span class="pl-kos">,</span> <span class="pl-s1">map</span><span class="pl-kos">)</span> <span class="pl-c1">=&gt;</span> <span class="pl-kos">{</span>
    <span class="pl-c">// the script part of the source, processed with all matching loaders</span>
    <span class="pl-c">// for does-not-exist.js</span>
  <span class="pl-kos">}</span><span class="pl-kos">)</span>

  <span class="pl-c">// even better if it returns Promise</span>
  <span class="pl-v">Promise</span><span class="pl-kos">.</span><span class="pl-en">all</span><span class="pl-kos">(</span><span class="pl-kos">[</span>
    <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-en">loadVirtualModule</span><span class="pl-kos">(</span><span class="pl-kos">{</span> ... <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">,</span> <span class="pl-c">// script</span>
    <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-en">loadVirtualModule</span><span class="pl-kos">(</span><span class="pl-kos">{</span> ... <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">,</span>  <span class="pl-c">// template</span>
    <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-en">loadVirtualModule</span><span class="pl-kos">(</span><span class="pl-kos">{</span> ... <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">,</span>  <span class="pl-c">// style</span>
  <span class="pl-kos">]</span><span class="pl-kos">)</span><span class="pl-kos">.</span><span class="pl-en">then</span><span class="pl-kos">(</span><span class="pl-s1">parts</span> <span class="pl-c1">=&gt;</span> <span class="pl-kos">{</span>
    <span class="pl-k">const</span> <span class="pl-kos">{</span> code<span class="pl-kos">,</span> map <span class="pl-kos">}</span> <span class="pl-c1">=</span> <span class="pl-s1">vueCompiler</span><span class="pl-kos">.</span><span class="pl-en">assemble</span><span class="pl-kos">(</span><span class="pl-s1">parts</span><span class="pl-kos">)</span>
    <span class="pl-s1">cb</span><span class="pl-kos">(</span><span class="pl-c1">null</span><span class="pl-kos">,</span> <span class="pl-s1">code</span><span class="pl-kos">,</span> <span class="pl-s1">map</span><span class="pl-kos">)</span>
  <span class="pl-kos">}</span><span class="pl-kos">)</span>
<span class="pl-kos">}</span></pre></div>
<p dir="auto">This would greatly simplify the implementation of <code class="notranslate">vue-loader</code> and solve the problems we are facing above.</p>
<p dir="auto">Is there a way to mangle/uglify Webpack globals? Option for it? Even hacky way?</p>
<p dir="auto">Few examples: <code class="notranslate">__webpack_exports__</code>, <code class="notranslate">moduleName__WEBPACK_IMPORTED_MODULE_0__</code></p>
<p dir="auto">My bundle is extremely size-sensitive and these are <strong>10-15% of my bundle</strong>.<br>
<a href="https://stackoverflow.com/questions/61216115/uglify-webpack-globals" rel="nofollow">https://stackoverflow.com/questions/61216115/uglify-webpack-globals</a></p>
<p dir="auto">Really sorry about question here but I've adventured like a week in SO, gitter, etc - no answers.</p>