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

Use a hash based on content instead of guid #30

Merged
merged 7 commits into from
Apr 15, 2024

Conversation

stryaponoff
Copy link
Contributor

I was experiencing some problems with my project again and here's how I've solved it.

The problem is vite-svg-2-webfont breaks build idempotence: e.g. if I execute vite build && mv dist _dist && vite build and the compare the _dist and dist directories, it will be completely different - for every single file.

This is because we using hashing mechanism to name assets and chunks:

build: {
  rollupOptions: {
    output: {
      assetFileNames: 'assets/[hash][extname]',
      chunkFileNames: 'assets/[hash].js',
      },
    },
  },

And the vite-svg-2-webfont is using guid() to make unique string for each build. This means that webfont reference inside a CSS will be different between two consequent builds, which means that the CSS file name will be changed because its content is changed, this means that CSS file reference will also be changed, and so on...

I was able to fix this behavior by just replacing the guid() call with some hashing algorithm but I decided to go further and fix another more problem: the build-time warnings.

Every time I was running vite build before, the missing assets warnings was thrown into a console, just a multiple lines like this:

/assets/material-design-icons-round-2fm2M2EJ.woff2 referenced in virtual:mdi-icons-round.css didn't resolve at build time, it will remain unchanged to be resolved at runtime

In this MR I refactored the build mechanisms so it will use normal Rollup build process. Due to its limitations while working with CSS and assets, I wasn't able to avoid some sharp corners, unfortunately, but it does the work anyway.

I will add some comments to clarify decisions in place.

const fileContents = Buffer.from(generatedFonts[type]);
const hash = getBufferHash(fileContents);
const filePath = pathJoin(TMP_DIR, `${processedOptions.fontName}-${hash}.${type}`);
ensureDirExistsAndWriteFile(fileContents, filePath); // write font file to a temporary dir
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here we're writing file to a system temporary dir. So this is workaround for a this.emitFile() mechanism which require us to wait a render-hooks which is called too lately.

Because we're emitting the file explicitly, Rollup will successfully find it and will not produce any warnings and will not be switched into a fallback logical branch.


const fileContents = Buffer.from(generatedFonts[type]);
const hash = getBufferHash(fileContents);
const filePath = pathJoin(TMP_DIR, `${processedOptions.fontName}-${hash}.${type}`);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've replaced the guid() call with hash based on a file contents. Technically speaking, there's no need to add some uniqueness here because the tmp dir is already unique, but it will make easier name-based comparation later in generateBundle() hook (which is required to keep external API working).

@@ -143,6 +163,7 @@ export function viteSvgToWebfont<T extends GeneratedFontTypes = GeneratedFontTyp
},
buildEnd() {
ac.abort();
rmDir(TMP_DIR);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just cleaning up the temporary files

generateBundle(_, bundle) {
for (const { type, href } of tmpGeneratedWebfonts) {
for (const chunk of Object.values(bundle)) {
if (chunk.name && href.endsWith(chunk.name)) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unfortunately, I can't find a way to get bundled asset filename by its entry name so here's the workaround where we're comparing the generated asset names with the fonts we generated earlier.

@stryaponoff stryaponoff marked this pull request as ready for review April 9, 2024 09:49
Copy link
Owner

@atlowChemi atlowChemi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is truly awesome! 🚀
I struggled with these warnings for a while before giving up and implementing the current implementation, so really nice to have this fixed! 😄

I've left some comments I would appreciate your response on before I merge this 🙂

src/fixtures/vite.basic.config.ts Outdated Show resolved Hide resolved
src/index.ts Show resolved Hide resolved
src/utils.ts Show resolved Hide resolved
src/utils.ts Show resolved Hide resolved
@stryaponoff
Copy link
Contributor Author

I've left some comments I would appreciate your response on before I merge this 🙂

Looks good. I'll try to fix this ASAP.

- Remove guid() function
- Remove guid() tests
- Add getBufferString() tests
- Add no-inline config
- Rename "build" test to "build:no-inline"
- Add "build" test for testing inline configs
@stryaponoff
Copy link
Contributor Author

stryaponoff commented Apr 15, 2024

Done! Here's what have I done:

  • removed guid() function and its tests
  • refactored build test to test the inline configs too
  • added getBufferHash() test

- Fix "build" test
Copy link
Owner

@atlowChemi atlowChemi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good!
Highly appreciated 🙏🏽

src/index.test.ts Outdated Show resolved Hide resolved
src/utils.test.ts Outdated Show resolved Hide resolved
src/utils.ts Outdated Show resolved Hide resolved
Copy link
Owner

@atlowChemi atlowChemi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry for the back-and-forth, and thanks for the hard work.
Awesome fix!

@atlowChemi atlowChemi changed the title Improve building process Use a hash based on content instead of guid Apr 15, 2024
@atlowChemi atlowChemi merged commit 6722807 into atlowChemi:main Apr 15, 2024
8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants