简体   繁体   中英

Babel is trying to import a module that doesn't exist

My compiled Babel output tries to import a function/file that does not exist. Am I missing a configuration or step in my Mix/Babel/Webpack configuration that would output this file?

I am using Laravel Mix (5.0.4) with its default configurations.

I've recently used the Javascript await operator for the first time. It is causing an issue with Babel. When Babel processes await to make it backwards compatible, it adds import _regeneratorRuntime from "@babel/runtime/regenerator"; to the beginning of the Javascript file. However, babel/runtime/regenerator doesn't actually exist. This causes the Javascript to fail when the browser attempts to load it, producing the error Error resolving module specifier: @babel/runtime/regenerator .

I am beyond my understanding of how Mix, Babel, and Webpack work together. I do not know how to tell Mix/Babel/Webpack to produce file(s) that contain the necessary module(s), or if there's something else I need to be doing.

I've tried many solutions via googling, played with the configuration files, and hit my head against my desk a bunch of times. None of these worked. I'm not sure if I am even asking the right questions.

Debugging info:

webpack.mix.js looks like this:

const mix = require('laravel-mix');

// Use of mix.babel() is imperative as this is legacy code and cannot leverage mix.js()
mix.babel('public/js/helpers.js', 'public/js/processed/helpers.js')
  .babel('public/js/main.js',     'public/js/processed/main.js')
  .babel('public/js/stripe.js',   'public/js/processed/stripe.js');

The problematic Javascript looks like this:

function foo() {
    const bar = document.getElementById('bar');

    bar.addEventListener('click', async (event) => {
        // ('async' is the part which causes the `import` to be added)
    });
}

And when run through Babel, looks like this:

import _regeneratorRuntime from"@babel/runtime/regenerator";function asyncGeneratorStep(n,e,r,t,o,a,u){try{var c=n[a](u),i=c.value}catch(n){return void r(n)}c.done?e(i):Promise.resolve(i).then(t,o)}function _asyncToGenerator(n){return function(){var e=this,r=arguments;return new Promise(function(t,o){var a=n.apply(e,r);function u(n){asyncGeneratorStep(a,t,o,u,c,"next",n)}function c(n){asyncGeneratorStep(a,t,o,u,c,"throw",n)}u(void 0)})}}function foo(){document.getElementById("bar").addEventListener("click",function(){var n=_asyncToGenerator(_regeneratorRuntime.mark(function n(e){return _regeneratorRuntime.wrap(function(n){for(;;)switch(n.prev=n.next){case 0:case"end":return n.stop()}},n)}));return function(e){return n.apply(this,arguments)}}())}

When I dig into Mix's default Babel config , I think it's using this:

{
    cacheDirectory: true,
    presets: [
        [
            '@babel/preset-env',
            {
                modules: false,
                forceAllTransforms: true
            }
        ]
    ],
    plugins: [
        '@babel/plugin-syntax-dynamic-import',
        '@babel/plugin-proposal-object-rest-spread',
        [
            '@babel/plugin-transform-runtime',
            {
                helpers: false
            }
        ]
    ]
}

Use js mixin instead:

const mix = require('laravel-mix');

mix.js('public/js/helpers.js', 'public/js/processed/helpers.js')
   .js('public/js/main.js',    'public/js/processed/main.js')
   .js('public/js/stripe.js',  'public/js/processed/stripe.js');

I was not able to find a working solution in a reasonable time for the legacy project I was working on, so I just used a workaround and documented it. I tried various solutions, different libraries and compilers, upgrading existing libraries, better workarounds and so on. Because this was a legacy project, most changes/updates/tool swaps resulted in a cascade of changes needed (and it still didn't work in the end after making all of those changes).

Ultimately, all I did was take the offending bit of Javascript (it was only one small function) and moved it to its own Javascript that does not get processed by Babel.

// The code that gets processed fine is here:
mix.babel('public/js/stripe.js', 'public/js/processed/stripe.js')
// The code that doesn't get processed without error is here:
.copy('public/js/stripeUnminified.js', 'public/js/processed/stripeUnminified.js');

Considering the time I had invested, this workaround was an ok solution. Running the offending bit of Javascript through a compiler such as Babel just wasn't actually a super critical priority considering all of the headache it was causing and time it was taking. It was looking like I was going to have to rework and update a lot of the project just to fix this one little problem (and still a fix was not guaranteed).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM