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

Module parse failed: Unexpected token (1:0) when combined with html-webpack-plugin #322

Open
4 tasks done
LariSinisalo opened this issue Oct 4, 2023 · 15 comments
Open
4 tasks done
Labels

Comments

@LariSinisalo
Copy link

LariSinisalo commented Oct 4, 2023

Reporting a bug?

When using webpack with both html-webpack-plugin and @intlify/unplugin-vue-i18n, the compilation fails with:

Error: Child compilation failed:
  Module parse failed: Unexpected token (1:0)
  File was processed with these loaders:
   * ./node_modules/unplugin/dist/webpack/loaders/load.js
   * ./node_modules/html-webpack-plugin/lib/loader.js
  You may need an additional loader to handle the result of these loaders.
  > <!DOCTYPE html>
  | <html>
  | <head>
... further lines omitted ...

The @intlify/unplugin-vue-i18n for some reason ends up as an additional loader for index.html, even though it is not being configured so. Omitting either plugin makes the compilation pass, so this seems to be a strange interaction between the plugins.

Expected behavior

I'd assume there should be no errors.

Reproduction

Please see https://stackblitz.com/edit/htmlplugin-t3ibcm

It should start building automatically and display the error in both terminal and the right hand side. If it does not start automatically, use in the terminal: npm install && npm start

System Info

System:
    OS: Linux 5.0 undefined
    CPU: (8) x64 Intel(R) Core(TM) i9-9880H CPU @ 2.30GHz
    Memory: 0 Bytes / 0 Bytes
    Shell: 1.0 - /bin/jsh
  Binaries:
    Node: 18.18.0 - /usr/local/bin/node
    Yarn: 1.22.19 - /usr/local/bin/yarn
    npm: 9.4.2 - /usr/local/bin/npm
    pnpm: 8.6.12 - /usr/local/bin/pnpm
  npmPackages:
    @intlify/unplugin-vue-i18n: ^1.4.0 => 1.4.0 
    vue-i18n: ^9.5.0 => 9.5.0

Screenshot

Screenshot from 2023-10-04 17-40-42

Additional context

No response

Validations

@LariSinisalo LariSinisalo added the Status: Review Needed Request for review comments label Oct 4, 2023
@LariSinisalo
Copy link
Author

Before creating the minimal reproduction sample, I tried to debug the compilation problem using the method documented at https://indepth.dev/posts/1166/this-will-make-you-more-efficient-at-debugging-webpack-unspecified-build-errors

This led to finding out that the error message source is from the index.html data being passed to a JavascriptParser:

Screenshot from 2023-09-26 17-29-45

In the above screenshot you can see the 'this.parser' value (JavascriptParser) and 'source' value (the index.html contents).

I did not manage to discover how that JavascriptParser ended up being used.

@LariSinisalo
Copy link
Author

I noticed that this issue would probably better fit under https://github.com/intlify/bundle-tools/ . If so, would it be possible to transfer this issue there?

@lk77
Copy link

lk77 commented Oct 4, 2023

The rules don't seems right :

module: {
    rules: [
      { enforce: 'post' },
      {
        enforce: 'post',
        use: [
          {
            loader: '/home/projects/htmlplugin-t3ibcm/node_modules/unplugin/dist/webpack/loaders/load',
            options: { unpluginName: 'unplugin-vue-i18n' }
          }
        ]
      },
      { test: /\.(.html)$/, exclude: /tests/, use: [ 'html-loader' ] },
      { test: /\.(json5?|ya?ml)$/, type: 'javascript/auto' }
    ]
  },

it seams the loader will process every single file

@LariSinisalo
Copy link
Author

Where did you find these rules? The rules block in the reproduction sample is empty, so is this a result generated by some later processing step?

@LariSinisalo
Copy link
Author

LariSinisalo commented Oct 6, 2023

By debugging the webpack run to check the rules, I noticed that in node_modules/unplugin/dist/index.js there is:

          if (plugin.load) {
            compiler.options.module.rules.unshift({
              include(id) {
                if (id.startsWith(plugin.__virtualModulePrefix))
                  id = decodeURIComponent(id.slice(plugin.__virtualModulePrefix.length));
                if (plugin.loadInclude && !plugin.loadInclude(id))
                  return false;
                return !externalModules.has(id);
              },
              enforce: plugin.enforce,
              use: [{
                loader: LOAD_LOADER2,
                options: {
                  unpluginName: plugin.name
                }
              }]
            });
          }

Here the plugin.loadInclude is undefined, and the function returns true for HTML files, too.

I tested modifying the include(id) function to have if(id.indexOf(".html") > 0) return false;, and that made the build pass successfully. This is not a fix, but it supports the above suggestion that there is something wrong with the rules.

@LariSinisalo
Copy link
Author

Even with a workaround in place, the @intlify/unplugin-vue-i18n seemed to interfere with source maps next.

I ended up moving the @intlify/unplugin-vue-i18n usage to a separate project that has no other plugins defined. This project only compiles the locale data to precompiled messages. The result of this workaround project is then read in the main project and provided via the messages parameter to createI18n from vue-i18n.runtime.esm-bundler.js.

Overall, to me it seems that @intlify/unplugin-vue-i18n attaches a bit too heavily into the Webpack build process and causes side effects in places it would not be expected to affect. When used in a separate project, it works fine.

@lk77
Copy link

lk77 commented Oct 9, 2023

i used https://www.npmjs.com/package/webpack-config-dump-plugin to dump the config, it's the rules added by the unplugin-vue-18n, i did not found where in the source code, i only found the { test: /\.(json5?|ya?ml)$/, type: 'javascript/auto' }, but not the other ones

https://stackblitz.com/edit/htmlplugin-t3ibcm-fxv235?file=webpack.config.dump

the html rules, i added it myself, but it did not solve anything

@kazupon
Copy link
Member

kazupon commented Oct 16, 2023

Thank you for reporting!
This issue is unplugin-vue-i18n.
So, I'll transfer to it.

@kazupon kazupon transferred this issue from intlify/vue-i18n Oct 16, 2023
@SuperSchek
Copy link

+1

@Druelik
Copy link

Druelik commented Jan 15, 2024

I have the same problem. Does anyone have a workaround or a bug fix for this?

@lehmat
Copy link

lehmat commented Jan 19, 2024

+1

@lehmat
Copy link

lehmat commented Jan 19, 2024

I got this working by doing separate webpack plugin that is triggered from main webpack. This ouputs translations to file that is used as precompiled messages. This is VERY HACKY SOLUTION, use with your own risk

CustomPlugin

const webpack                 = require('webpack');
const VueI18nPlugin           = require('@intlify/unplugin-vue-i18n/webpack')
const path                    = require('path');

class NestedCompilationPlugin {
  apply(compiler) {
    compiler.hooks.beforeCompile.tapAsync('NestedCompilationPlugin', (compilation, callback) => {
      const nestedCompilerConfig = {
        mode: 'development',
        devtool: 'source-map',
        entry: path.resolve(__dirname, '../src/translations/compile.js'),
        output: {
          path: path.resolve(__dirname, '../src/translations/precompiled'),
          filename: 'nestedBundle.js',
          library: 'translations',
          libraryTarget: 'commonjs2',
        },
        plugins: [
          VueI18nPlugin({
            include: [path.resolve(__dirname, '../src/translations/locales/**')]
          })
        ]
      };

      const nestedCompiler = webpack(nestedCompilerConfig);

      nestedCompiler.run((err, stats) => {
        if (err) {
          console.error(err);
          return callback(err);
        }

        console.log(stats.toString({
          colors: true
        }));

        callback();
      });
    });
  }
}

module.exports = NestedCompilationPlugin;

In your main webpack import and add this plugin to plugins

../src/translations/compile.js

import { createI18n } from 'vue-i18n/dist/vue-i18n.runtime.esm-bundler.js'
import fi from './locales/fi.json'
import sv from './locales/sv.json'
import en from './locales/en.json'

const i18n = createI18n({
  legacy: false,
  locale: 'en',
  messages: {
    fi,
    sv,
    en,
  },
})

export default i18n

Changes to your main webpack createI18n

import { createI18n } from 'vue-i18n/dist/vue-i18n.runtime.esm-bundler.js'
import { translations } from './precompiled/nestedBundle.js'

const i18n = createI18n({
  locale: process.env.VUE_APP_I18N_LOCALE || 'en',
  allowComposition: true,
  fallbackLocale: process.env.VUE_APP_I18N_FALLBACK_LOCALE || 'en',
  messages: translations.default.global.messages.value,
})


export default i18n

@ForesightImaging
Copy link

First time testdriving and hit this issue with html-loader.
I tried a few things like changing plugin order, tweaking options and down reving to 1.6. I get the same errors as the other folks.

@Arlisaha
Copy link

Arlisaha commented Mar 8, 2024

I have the same issue. However, it seems it only occurs using ejsformat. I switched to hbs and it disappeared.

@Narretz
Copy link

Narretz commented Oct 14, 2024

@kazupon since you seem to be active in development, can you look into this?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

9 participants