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

[vite:build-html] Unable to parse html in build step #4067

Closed
6 tasks done
AlonMiz opened this issue Jul 1, 2021 · 19 comments · Fixed by #5342
Closed
6 tasks done

[vite:build-html] Unable to parse html in build step #4067

AlonMiz opened this issue Jul 1, 2021 · 19 comments · Fixed by #5342
Labels
feat: html p3-minor-bug An edge case that only affects very specific usage (priority)

Comments

@AlonMiz
Copy link

AlonMiz commented Jul 1, 2021

Describe the bug

using vite with vite-plugin-string for importing html as strings
dev mode works great, but when trying to build for production, we encounter the error below.
the expected behavior is to not try to traverse all of my HTMLs as I don't care if it's valid or not.
my index.html is perfectly valid but my other dozen HTML files that we import as strings are not all valid (in syntax).

[vite:build-html] Unable to parse {"file":"src/app/outer/register/register.html","line":1,"column":29}
1  |  export default "Already have an account?</a>\n                </div>\n            </div>\n\n        </div>\n    </form>\n</div>\n";
   |                              ^
file: src/app/outer/register/register.html
error during build:
Error: Unable to parse {"file":"src/app/outer/register/register.html","line":1,"column":29}
1  |  export default "Already have an account?</a>\n                </div>\n            </div>\n\n        </div>\n    </form>\n</div>\n";
   |                              ^
    at traverseHtml (/node_modules/vite/dist/node/chunks/dep-0ed4fbc0.js:24398:15)
    at async Object.transform (/node_modules/vite/dist/node/chunks/dep-0ed4fbc0.js:24453:17)
    at async ModuleLoader.addModuleSource (/node_modules/vite/node_modules/rollup/dist/shared/rollup.js:18616:30)
    at async ModuleLoader.fetchModule (/node_modules/vite/node_modules/rollup/dist/shared/rollup.js:18672:9)
    at async /vite/node_modules/rollup/dist/shared/rollup.js:18647:48
    at async Promise.all (index 3)
    at async ModuleLoader.fetchDynamicDependencies (/vite/node_modules/rollup/dist/shared/rollup.js:18637:30)
    at async Promise.all (index 1)
    at async ModuleLoader.fetchModule (/node_modules/vite/node_modules/rollup/dist/shared/rollup.js:18674:9)
    at async Promise.all (index 0)

Reproduction

using vite-plugin-string while importing broken html syntax that is not the index.html

if (id.endsWith('.html')) {

basically should check only my index.html and not the rest of the HTML tree

System Info

System:
    OS: macOS 11.4
    CPU: (16) x64 Intel(R) Core(TM) i9-9980HK CPU @ 2.40GHz
    Memory: 5.09 GB / 32.00 GB
    Shell: 5.8 - /bin/zsh
  Binaries:
    Node: 15.6.0 - ~/.volta/tools/image/node/15.6.0/bin/node
    Yarn: 1.22.10 - ~/.volta/tools/image/yarn/1.22.10/bin/yarn
    npm: 7.19.0 - ~/.volta/tools/image/npm/7.19.0/bin/npm
  Browsers:
    Chrome: 91.0.4472.114
    Firefox: 84.0
    Safari: 14.1.1

Used Package Manager

yarn

Logs

vite:config using resolved config: {
  vite:config   root: '/app-frontend/src',
  vite:config   logLevel: 'info',
  vite:config   server: {
  vite:config     fsServe: { root: '/Users/***/****', strict: false }
  vite:config   },
  vite:config   resolve: {
  vite:config     dedupe: undefined,
  vite:config     alias: [
  vite:config       [Object], [Object], [Object],
  vite:config       [Object], [Object], [Object],
  vite:config       [Object], [Object], [Object],
  vite:config       [Object], [Object], [Object],
  vite:config       [Object], [Object], [Object],
  vite:config       [Object], [Object], [Object],
  vite:config       [Object], [Object], [Object],
  vite:config       [Object], [Object]
  vite:config     ]
  vite:config   },
  vite:config   plugins: [
  vite:config     'alias',
  vite:config     'react-refresh',
  vite:config     'vite:dynamic-import-polyfill',
  vite:config     'vite:resolve',
  vite:config     'vite:html',
  vite:config     'vite:css',
  vite:config     'vite:esbuild',
  vite:config     'vite:json',
  vite:config     'vite:wasm',
  vite:config     'vite:worker',
  vite:config     'vite:asset',
  vite:config     'vite-plugin-string',
  vite:config     'vite-plugin-checker',
  vite:config     'vite:injectHtml',
  vite:config     'vite:define',
  vite:config     'vite:css-post',
  vite:config     'vite:build-html',
  vite:config     'commonjs',
  vite:config     'vite:data-uri',
  vite:config     'rollup-plugin-dynamic-import-variables',
  vite:config     'vite:import-analysis',
  vite:config     'vite:esbuild-transpile',
  vite:config     'vite:terser',
  vite:config     'vite:reporter'
  vite:config   ],
  vite:config   build: {
  vite:config     target: [ 'es2019', 'edge88', 'firefox78', 'chrome87', 'safari13.1' ],
  vite:config     polyfillDynamicImport: false,
  vite:config     outDir: 'dist',
  vite:config     assetsDir: 'assets',
  vite:config     assetsInlineLimit: 4096,
  vite:config     cssCodeSplit: true,
  vite:config     sourcemap: false,
  vite:config     rollupOptions: {},
  vite:config     commonjsOptions: { include: [Array], extensions: [Array] },
  vite:config     minify: 'terser',
  vite:config     terserOptions: {},
  vite:config     cleanCssOptions: {},
  vite:config     write: true,
  vite:config     emptyOutDir: null,
  vite:config     manifest: false,
  vite:config     lib: false,
  vite:config     ssr: false,
  vite:config     ssrManifest: false,
  vite:config     brotliSize: true,
  vite:config     chunkSizeWarningLimit: 500,
  vite:config     watch: null
  vite:config   },
  vite:config   configFile: '/app-frontend/vite.config.js',
  vite:config   configFileDependencies: [],
  vite:config   inlineConfig: {
  vite:config     root: undefined,
  vite:config     base: undefined,
  vite:config     mode: undefined,
  vite:config     configFile: undefined,
  vite:config     logLevel: undefined,
  vite:config     clearScreen: undefined,
  vite:config     build: {}
  vite:config   },
  vite:config   base: '/',
  vite:config   publicDir: '/app-frontend/src/public',
  vite:config   cacheDir: '/app-frontend/node_modules/.vite',
  vite:config   command: 'build',
  vite:config   mode: 'production',
  vite:config   isProduction: false,
  vite:config   env: { BASE_URL: '/', MODE: 'production', DEV: true, PROD: false },
  vite:config   assetsInclude: [Function: assetsInclude],
  vite:config   logger: {
  vite:config     hasWarned: false,
  vite:config     info: [Function: info],
  vite:config     warn: [Function: warn],
  vite:config     warnOnce: [Function: warnOnce],
  vite:config     error: [Function: error],
  vite:config     clearScreen: [Function: clearScreen]
  vite:config   },
  vite:config   createResolver: [Function: createResolver],
  vite:config   optimizeDeps: { esbuildOptions: { keepNames: undefined } }
  vite:config } +25ms

Validations

@patak-dev
Copy link
Member

@AlonMiz this looks like an issue with vite-plugin-string, did you open an issue there first?

@AlonMiz
Copy link
Author

AlonMiz commented Jul 1, 2021

@patak-js, why do you think it's on vite-plugin-string side?
actually, I just tried running without that plugin and I got the same output.
my guess is that my problem is that vite assumes that every .html file is part of some entry and it tries to traverse and minify it.
this is the line where it assumes that every HTML should be traversed

if (id.endsWith('.html')) {

maybe there's a way to ignore that step somehow.
Thanks

@patak-dev
Copy link
Member

That makes sense, if the .html is imported, then internal plugins shouldn't be touching it. It would be good to get a fix for this.

But instead of using vite-plugin-string, you can use

import part from './part.html?raw'

And you will get the file content as a string, without internal plugins kicking in.

@AlonMiz
Copy link
Author

AlonMiz commented Jul 2, 2021

@patak-js thanks
ok, that could work
EDIT: unfortunately, that does not work. tried replacing all imports with regex to XXX.index?raw, but getting the same error
EDIT2: I had some other issue, and now it does work but with all the below caveats

but it has several downsides with that:

  1. we are still using webpack to compile to production. adding ?raw might not work as expected with the webpack syntax.
    but even if it does, it still feels a bit clumsy.
  2. we get an eslint error Unable to resolve path to module './login.html?raw'.eslintimport/no-unresolved
    we want to migrate all of the features we need in vite+rollup
  3. the third downside is that we need to go over each file of our hundreds of HTMLs imports, or create some regex to do that. possible but not convinient.
  4. apparently TS have issues with that as well
src/admin/admin.app.ts:27:36 - error TS2307: Cannot find module '../directives/app-breadcrumbs/app-breadcrumbs.html?raw' or its corresponding type declarations.

27 import appBreadCrumbsTemplate from '../directives/app-breadcrumbs/app-breadcrumbs.html?raw';

alternative:

  1. there should be a config that defines what extensions/glob/includes one wants to load as raw.
    looking at some places encountering that same issue
    vite-cannot-handle-xxx-html-files
    vite-in-a-simple-html-js-usecase
  2. as you've said, if I'm using a plugin that transpiles a file, vite should not assume it needs to do it either.

@patak-dev
Copy link
Member

If you get to build minimal reproduction for some of the issues (like the TS), that could be a good bug report to improve the ?raw feature.

I let other comments on possible solutions for vite not dealing with .html files, but that indeed seems like a good fix. Maybe a good idea to create a PR so it can be discussed there.

@patak-dev patak-dev added bug feat: html p3-minor-bug An edge case that only affects very specific usage (priority) and removed pending triage labels Jul 2, 2021
@AlonMiz
Copy link
Author

AlonMiz commented Jul 2, 2021

@patak-js it did work eventually, but we still have the caveats i mentioned

  1. we are still using webpack to compile to production. adding ?raw might not work as expected with the webpack syntax.
    but even if it does, it still feels a bit clumsy.
  2. we get an eslint error Unable to resolve path to module './login.html?raw'.eslintimport/no-unresolved
    we want to migrate all of the features we need in vite+rollup
  3. the third downside is that we need to go over each file of our hundreds of HTMLs imports or create some regex to do that. possible but not convenient.
  4. apparently TS have issues with that as well

@AlonMiz
Copy link
Author

AlonMiz commented Jul 2, 2021

i was able to resolve all of the above issues.
so for everyone that got here in the future:

  1. ?raw is a valid node/ESM import syntax as it should support urls
  2. eslint issue can be resolved by adding webpack resolver eslint-import-resolver-webpack
  3. ts issue can be resolved by adding declare module '*.html?raw'; to a types.d.ts in your workspace/package folder
  4. the regex i used was
    (import .* from .*)\.html to $1.html?raw

I would still expect some better solution for ?raw imports. some kind of config

build: {
   raw: {
       extenstions : ['html', 'txt'],
       glob: ['**.html'] // or glob
   }
}

@AlonMiz
Copy link
Author

AlonMiz commented Jul 18, 2021

having a new issue. due to the addition of the ?raw suffix to all HTML imports

import './login.html?raw'

jest started to fail with unable to resolve those modules

    Cannot find module './alert-disabled.html?raw' from 'services/services.config.js'

loading a module with query params is a missing feature in jest
jestjs/jest#4181

so, I had to use this babel plugin and add it to my babel-jest transformer

babelConfig.plugins.push('babel-plugin-import-remove-resource-query');
module.exports = require('babel-jest').createTransformer(babelConfig);

so now that's the 5th issue with this raw loader. @patak-js, I wish there were a better way to achieve what I asked for 😞

@svi3c
Copy link

svi3c commented Aug 4, 2021

@AlonMiz I just used the moduleNameMapper as a solution for the jest problem. I use my custom html plugin, but maybe this works for the raw plugin:

moduleNameMapper: {
  "^(.*).html\\?raw": `\$1.html`
}

@AlonMiz
Copy link
Author

AlonMiz commented Aug 5, 2021

@svi3c this is perfect. thanks a lot!

@AlonMiz
Copy link
Author

AlonMiz commented Nov 3, 2021

@dimfeld thanks alot for the submitted pr. i hope it can be merged soon
I now experience another issue.
i think it's related, something got changed in one of the new versions
I now get errors from vite:import-analysis, which is probably similar to what build-html is trying to do

3:37:47 PM [vite] Internal server error: Failed to parse source for import analysis because the content contains invalid JS syntax. You may need to install appropriate plugins to handle the .html file format.
  Plugin: vite:import-analysis
  File: /app-frontend/src/app/dashboard/insights/insights-tab/edit-insight/edit-insight.html
  1  |  <div class="dialog edit-insight-container"dialog-close="closeThisDialog()">
  2  |      <dialog-header text="edit insight"></dialog-header>
     |                                                                   ^
  3  |
  4  |      <div class="explanation-message">
      at formatError (/node_modules/vite/dist/node/chunks/dep-85dbaaa7.js:42189:46)
      at TransformContext.error (/node_modules/vite/dist/node/chunks/dep-85dbaaa7.js:42185:19)
      at TransformContext.transform (/node_modules/vite/dist/node/chunks/dep-85dbaaa7.js:67251:22)
      at async Object.transform (/node_modules/vite/dist/node/chunks/dep-85dbaaa7.js:42396:30)
      at async doTransform (/node_modules/vite/dist/node/chunks/dep-85dbaaa7.js:56797:29)

@rpivo
Copy link

rpivo commented Dec 30, 2021

I am also running into this issue. I built a custom plugin that imports html files as strings (not using vite-plugin-string). This works fine with Vite's dev script, but I'm getting the above error for build.

@rpivo
Copy link

rpivo commented Dec 30, 2021

@patak-dev 's suggestion to use import part from './part.html?raw' worked great -- thanks!

@AlonMiz
Copy link
Author

AlonMiz commented Jan 13, 2022

@dimfeld @rpivo Thanks a lot for that!

I can report that the issue has been resolved
we are moving towards replacing our webpack and enjoying vite super fast watch and compilation

yarn run v1.22.10
$ vite build --emptyOutDir
vite v2.7.10 building for production...
transforming (4760) 
✓ 4768 modules transformed.
../dist/assets/apple-icon-57x57.d2fdfdf7.png                    4.40 KiB
../dist/assets/apple-icon-60x60.fd6ea6b3.png                    4.67 KiB
...
✨  Done in 33.77s.

while webpack takes 64.92s

@github-actions github-actions bot locked and limited conversation to collaborators Jan 28, 2022
IanVS added a commit to IanVS/vite that referenced this issue Feb 1, 2022
@vitejs vitejs unlocked this conversation Feb 2, 2022
@Niputi Niputi reopened this Feb 2, 2022
@erhanyasar
Copy link

FYI, it's also related to use of experimental features. Removing experimental object with renderBuiltUrl parameter from vite.config.js for version 3.0.9 helped me to work around it.

I didn't take a look at it further but, I think it should be most probably same for all versions with 3.0.x . Maybe it's my bad that I missed reading it but, it's probably same for all experimental features.

Here is the documentation I used before to implement advanced base options. @patak-dev.

@juanvictorbascopecastro
Copy link

juanvictorbascopecastro commented Nov 13, 2022

I have an error when building with vite, I have the following code in my index.html <link rel="stylesheet" href="./public/themes/lara-light-indigo/theme.css" id="theme-link">. but when building it does not do it correctly since I get an error in document.getElementById('theme-link); I get undefined, I add it manually id="theme-link" but the javascript code does not do its job

@erhanyasar
Copy link

I have an error when building with vite, I have the following code in my index.html <link rel="stylesheet" href="./public/themes/lara-light-indigo/theme.css" id="theme-link">. but when building it does not do it correctly since I get an error in document.getElementById('theme-link); I get undefined, I add it manually id="theme-link" but the javascript code does not do its job

@juanvictorbascopecastro you should wait page to be ready in that case via window.onload, document.ready, etc.

@bluwy
Copy link
Member

bluwy commented Nov 17, 2022

@juanvictorbascopecastro that's because Vite merges the CSS files for code splitting by default, so the id is lost. Right now the only way to have Vite not do that is with the media and disabled prop on the link tag, but that has caveats (#9402).

I don't think this is related to this issue though. @Niputi is there a reason you re-opened this issue?

@Niputi
Copy link
Contributor

Niputi commented Nov 17, 2022

@bluwy sorry, don't remember. Just close it

@bluwy bluwy closed this as completed Nov 17, 2022
@github-actions github-actions bot locked and limited conversation to collaborators Dec 2, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
feat: html p3-minor-bug An edge case that only affects very specific usage (priority)
Projects
None yet
Development

Successfully merging a pull request may close this issue.

8 participants