stencil icon indicating copy to clipboard operation
stencil copied to clipboard

hashFileNames not working properly - not every file is hashed. This results in broken components

Open hvgeertruy opened this issue 4 years ago • 5 comments

Stencil version:

@stencil/[email protected] 

I'm submitting a: [X] bug report [ ] feature request [ ] support request => Please do not submit support requests here, use one of these channels: https://stencil-worldwide.herokuapp.com/ or https://forum.ionicframework.com/

Current behavior: We have a hash mismatch on stencil files which will fail to load component(s) and throw an error.

We have the following files generated in the esm folder:

  • components/esm/index-5010886e.js
  • my-component.entry.js
  • my-second-component.entry.js

The entry files contain a reference to the index file.

my-component.entry.js

import { r as registerInstance, c as createEvent, h, H as Host } from './index-5010886e.js';
...
  • When the hash of the index file changes, it will try to load the component entry files. Because it is hashed, it will defeat the browser caching mechanism (which is good).
  • When loading the component entry file, the browser will use the cached version (there is no cache defeating mechanism on the file - this is bad).
  • because the entry files have a reference to a hashed index file, it will throw an error and fail to load the component. The application will show blank spots instead of a component.

Note: This will not happen if browser caching is turned off.

Expected behavior: Like the index.js, The entry files should have a hash. This will prevent browsers from caching the files and causing an error, because the hash of the index file and the reference in the entry file do not match.

  • give all {component}.entry.js files the same hash as the index.hash.js file > {component}.hash.entry.js
  • make sure that the index.hash.js file loads the bundle with the hash (line 1495)

Steps to reproduce:

  • Do a stencil build
  • open a browser, make sure caching is turned on and navigate to a page where the components are used
  • trigger a hash change (not sure what triggers this - presumably a stenciljs version upgrade or, as the documentation specifies, by a content change)
  • Do another stencil build
  • refresh the page on the browser

Related code:

index.hash.js (compiled)

const loadModule = (cmpMeta, hostRef, hmrVersionId) => {
    // loadModuleImport
    const exportName = cmpMeta.$tagName$.replace(/-/g, '_');
    const bundleId = ( cmpMeta.$lazyBundleIds$);
    const module =  cmpModules.get(bundleId) ;
    if (module) {
        return module[exportName];
    }
    return import(
    /* webpackInclude: /\.entry\.js$/ */
    /* webpackExclude: /\.system\.entry\.js$/ */
    /* webpackMode: "lazy" */
    `./${bundleId}.entry.js${ ''}`).then(importedModule => { // <-- THIS PART LOADS ENTRIES W/H HASH
        {
            cmpModules.set(bundleId, importedModule);
        }
        return importedModule[exportName];
    }, consoleError);
};

Other information: Stencil documentation specifies this on the topic:

source: https://stenciljs.com/docs/config ` hashFileNames default: true

During production builds, the content of each generated file is hashed to represent the content, and the hashed value is used as the filename. If the content isn't updated between builds, then it receives the same filename. When the content is updated, then the filename is different. By doing this, deployed apps can "forever-cache" the build directory and take full advantage of content delivery networks (CDNs) and heavily caching files for faster apps. `

This information seems to be incorrect. It states that each generated file is hashed, while it does not hash *.entry.js files

hvgeertruy avatar Aug 07 '20 09:08 hvgeertruy

I had a similar problem when I use a web component built with Stencil: the .entry File was served from cache, while index file was "fresh" (because it was hashed). That lead to some strange errors, which disappeared when the cache was emptied.

I worked around the problem by loading the files from www/build instead of from dist. In www/build, all files are nicely hashed, so no more issues with caching when I deploy a new version.

Is the www/build directory meant to be used for that purpose?

msandberger avatar Oct 08 '20 10:10 msandberger

Did you guys found a solution ? The issue is the same with www/build repository, all files are not hashed (espacially the files we need to use :) )

KevinCarnaille2 avatar May 26 '21 09:05 KevinCarnaille2

We ended up using a different implementation method.

And yes, i believe you can use the build files, but they are not meant to be used for production builds.

hvgeertruy avatar May 26 '21 15:05 hvgeertruy

Same as this issue: https://github.com/ionic-team/stencil/issues/2526

mikkelrom avatar Jul 12 '21 12:07 mikkelrom

Following this issue: Our temp workaround is changing the name of the directory to build our theme whenever we make any changes to the web component. 👎

Farnoosh63 avatar May 13 '22 18:05 Farnoosh63