Skip to content

Scope ID Hash Salting #1716

@SudoSloth

Description

@SudoSloth

What problem does this feature solve?

When hosting multiple instances of Vue (compiled and built with different versions, by different third-party developers, from uncontrolled environments, etc) in the same browser (For instance, in a micro-front-end environment) which are consumed dynamically by a host interface, it has been observed that styles from one application may bleed in to another when the individual applications are not built using the option productionMode: true.

In this scenario, it is preferred to test functionality of the prototype application in "Development" mode against other applications similarly built. We may also provide third-party developers with boiler-plate apps, so we can reasonably expect a common setup for the application directory structure, naming conventions and bundling to aid developers get up and running quickly. Generally, one would expect the production mode to be set via the environment arguments, but currently, in order for the styles to not bleed, we have to work around this issue by using the productionMode: true option.

Under these admittedly edge-case circumstances, it has been observed that the vue-loader functionality for creating the CSS scope ID needs to be a little more robust then it currently is, as under the conditions, it is possible to achieve css hash collision making for conflicting app styles.

What does the proposed API look like?

The simplest alteration to the code to prevent hash conflict would simply be to alter line 94 of /lib/index.js
from:

index.js/

const id = hash(
  isProduction
    ? (shortFilePath + '\n' + source)
    : shortFilePath
)

into

const id = hash(shortFilePath + '\n' + source)

Adding the source to the hash routine, even during non-production routine would ensure that both the hash, and any conflicting apps would be identical (which in practice should be observably correct). A side effect might be that this may slow down the hash routine, and therefore, slow dev builds - though I have no metrics to back this up.

Another easily achievable option would be to provide a "salt" option for the hash routine to aid uniqueness.

index.d.ts, line 8

interface VueLoaderOptions {
    ...
    scopeIdHashSalt?: string
}

index.js, line 94

const hashValue = isProduction
    ? (shortFilePath + '\n' + source)
    : shortFilePath

const hashSalt = options.scopeIdHashSalt || ''

const id = hash(hashValue + hashSalt)

The value of this option is that I would expect it not to impact your current tests as much as the first example but is a sure-fire means of removing the chance of hash collisions unless the developer is extremely unlucky.

Another option might be simply to use a timestamp as a bit of salt - I tentatively suggest this might be enough but testing ID generation would be troublesome.

To the Vue developers:
My apologies if you feel that this should have been a bug report - After reading the code for vue-loader I wasn't sure whether this qualified as bug or a feature, since the code looked to intentionally distinguish between production and development during the hash routine, and since salting your hash was not a feature already integrated I opted to use the feature request.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions