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

Option not to include hash to file names #3855

Open
FixRM opened this issue Jan 18, 2018 · 34 comments
Open

Option not to include hash to file names #3855

FixRM opened this issue Jan 18, 2018 · 34 comments

Comments

@FixRM
Copy link

FixRM commented Jan 18, 2018

First of all thanks for this tool! It was really helpful for me to get started. I read all available how-to's and materials and really understand the purpose of this tool BUT... If this app is agnostic of the backend, and just produces static HTML/JS/CSS bundles there should be an option to leave filenames as is, as some ECM/CMS and other host systems has their own caching/versioning realization. Having different file names after each build mean need for manually deal with file published previously.

@gaearon
Copy link
Contributor

gaearon commented Jan 18, 2018

Having different file names after each build mean need for manually deal with file published previously.

Can you expand on how this creates the difficulty? What is the workflow like?

@FixRM
Copy link
Author

FixRM commented Jan 18, 2018

Hi! The workflow is following: CMS has it's own internal project-solution tracking system. Each web resource (html/css/js etc.) is saved in database and filename is used as alternative key for tracking project dependencies, or doing updates. If file name is changed the are two options for me: update each resource manually after each change or publish them as new resources. If I choose second option I'll have mess of unused resources in my project but they still be tracked as dependencies and will be moved to production environment after project import / export process.

@heyimalex
Copy link
Contributor

If you're looking for a solution right now, there are definitely ugly ways to automate this using asset-manifest.json, which is a sort of mapping from the original names to the hashed names.

@FixRM
Copy link
Author

FixRM commented Jan 19, 2018

Thanks. As for now I choose eject and modify webpack config in 3 or 5 places. That's why I'm proposing a centralized option suitable for config or doing fork

@andriijas
Copy link
Contributor

Feels like a very specific use case. Most users benefit from cache busting naming convention. Being able to set far future expire headers on static assets speeds loading up of the site for revisits. It sounds like you can read the asset-manifest and feed your DB with it.

@FixRM
Copy link
Author

FixRM commented Jan 22, 2018

Unfortunately it's not specific in MS world. In most cases we have to include static files to Visual Studio projects to be able to publish them. There is specific but it's normal case here.

@gaearon
Copy link
Contributor

gaearon commented Jan 22, 2018

If you're looking for a solution right now, there are definitely ugly ways to automate this using asset-manifest.json, which is a sort of mapping from the original names to the hashed names.

This does sound like the right way to me. And you could right an automated script that reads it, does something, and even share that script between projects.

@FixRM
Copy link
Author

FixRM commented Jan 23, 2018

Sorry but I can't understand how can it help me if build command will generate index.html with references to files with hashes?

@heyimalex
Copy link
Contributor

Hm, I was thinking more that you could feed your cms with it. Is there really no way to specify renamed resources, or to remove old resources from the project? Since the main issue is the "mess of unused resources".

If that's not an option, then ejecting is probably the best bet right now. You could do find/replace and rename using the asset manifest, but thinking about it now it might break source maps.

@deanolium
Copy link

Whilst this is something which is rare, there are some use cases for this. For my company, we develop web apps to be served on a survey platform. This platform allows us to upload the .js and .css files onto their site, but the relevant contents of the index.html has to be copy/pasted into a question form on this platform (ie, a HTML block). Currently hashing means every time we do a change to the code, we not only have to upload the bundles, but then manually go to the html block, copy/paste the new name of the bundle and resave that page. Being a manual process, this is error-prone as well as plain slow.

Being able to turn hashing off would save a lot of pain and potential errors for this use-case. Obviously we can just eject, but that is meant to be a last resort.

@WolfieZero
Copy link

I'm currently in this situation where the hashing in filenames causes issues. Whilst ejecting is a solution, it seems like a broken solution.

@FixRM
Copy link
Author

FixRM commented Feb 2, 2018

@WolfieZero, I did a fork and made some changes in react scripts package to get static names after build. It may be not best way but it is still much better then doing eject. Please refer to this manual: https://auth0.com/blog/how-to-configure-create-react-app/. As far as I understand it is supported approach

@WolfieZero
Copy link

@FixRM Awesome, will take a look at. Thanks!

@FixRM
Copy link
Author

FixRM commented Feb 2, 2018

@WolfieZero You can try mine but it uses TypeScript: https://github.com/FixRM/create-react-app-typescript-static

@Havret
Copy link

Havret commented May 15, 2018

Why don't you add query hashes instead of hashing file names?

<script src="/dist/main.js?v=Ot9snoX65g3EUGmCjVcSfFaUnYukk6lhhZJs0HZKRD8"></script>

If you generate your HTML in that way everyone should be satisfied.

@ianschmitz
Copy link
Contributor

@Havret the downside to query strings is intermediate proxies (such as CDNs) will often ignore the query string by default.

@santimendoza
Copy link

I am needing this to (bundles without hashes). I dont think it to be so hard to implement. And should be like and option (by default include the hashes)

@NateAGeek
Copy link

NateAGeek commented Jul 20, 2018

Something that I was able to do with React Rewired (https://github.com/timarney/react-app-rewired). I will say that if you are really overriding a lot in the future it might be worth ejecting.

// config-overrides.js
module.exports = {
  webpack: function(config, env) {
    if (env === "production") {
      //JS Overrides
      config.output.filename = 'static/js/[name].js';
      config.output.chunkFilename = 'static/js/[name].chunk.js';

      //CSS Overrides
      config.plugins[4].filename = 'static/css/[name].css';

      //Media and Assets Overrides
      config.module.rules[1].oneOf[0].options.name = 'static/media/[name].[ext]';
      config.module.rules[1].oneOf[3].options.name = 'static/media/[name].[ext]';
     /**
       * If the media/assets public path differs on the server
       * 
       * config.module.rules[1].oneOf[0].options.name = 'static/media/[name].[ext]';
       * config.module.rules[1].oneOf[0].options.publicPath = '/public/assets/';
       * config.module.rules[1].oneOf[3].options.name = 'static/media/[name].[ext]';
       * config.module.rules[1].oneOf[3].options.publicPath = '/public/assets/';
       */

    }

    return config;
  }
};

This should take care of the hashes, mapping, and media/asset. Sadly with the way plugins are implemented in an array, I have to use fixed indexes. Also, if you do end up adding more plugins it could mess with those fixed indexes.

@BrunoDesthuilliers
Copy link

We serve our react app from Django staticfiles, and we use Django's builtin CachedStaticfFilesStorage, which itself takes care of hashing all static assets etc, so we end up with a doubly hashed bundle :-/ This is really a PITA and I really don't understand why there's no simple option to deactivate hashing in create-react-app. Really, why force peoples to go through all sorts of hoops just to make things work for their own use case ?

@dlbnco
Copy link

dlbnco commented Mar 8, 2019

I'm also having issues with this, here is the scenario:

The app is hosted on Netlify. Since it's a SPA, redirect rules are set to redirect any route to index.html.

First access to app caches the current bundle name. If a new deployment/build is done, a new bundle name is generated.

In a second access, the browser still requests old bundle name generated on first build. Server doesn't find requested js file, so redirect rules apply and index.html is served as a js file.

Result is a blank page and the following error on console since it tries to read js but server delivers a HTML file:

Unexpected token <

@route2Dev
Copy link

Other SPA framework (Angular / Vue) CLIs support this. Ejecting feels like taking a sledge hammer to crush an ant.

Having non-hased output files is helpful if you are using something other than the generated index.html to host the SPA. An example would be hosting a new React SPA in a razor (.cshtml) view in an existing ASP.NET MVC project. I want / need the script src locations to be known at development time as this file is under source control.

Otherwise, I could update my build server to perform magic to insert the for my production builds. But then what I deploy is not reflected in source control.

Without the hashed files, cache busting would be up to the developer. But that's the trade-off we would be willing to make for predictability.

@djyadav
Copy link

djyadav commented May 23, 2019

@dlbnco We are facing the exactly same issue. So, The application fails if we deploy it while a user is online.

The app is hosted on Netlify. Since it's a SPA, redirect rules are set to redirect any route to index.html.

First access to app caches the current bundle name. If a new deployment/build is done, a new bundle name is generated.

In a second access, the browser still requests old bundle name generated on first build. Server doesn't find requested js file, so redirect rules apply and index.html is served as a js file.

Result is a blank page and the following error on console since it tries to read js but server delivers a HTML file.

@Kyr
Copy link

Kyr commented Jul 21, 2019

May I suggest that #7172 may resolve such problem without ejecting?

@Stv1
Copy link

Stv1 commented Aug 20, 2019

hello could someone correct this? i have the same problem.

@BrunoDesthuilliers
Copy link

Ok so we now have at least half a dozen users that explicitely claimed they had a need for this feature (which means quite a few others also do who have not posted here yet), and at least a couple more-or-less supported "solutions" (either forks or workaround like react-app-rewired). Not mentionning those who choosed to "eject" but would rather not have if they add a better (builtin) solution.

May I kindly suggest that it may not be such a "very specific use case" and that the fact that "Most users benefit from cache busting naming convention" is actually unrelated since the point is not to remove this feature but only to add an option to deactivate it ? (without having to deal with the inconveniences of the existing "solutions", that is).

FWIW I'm actually a bit suprised that Kyr's PR (cf #7172) was rejected on the premise that "this has little value for most users" - it obviously has for quite a few of us, and AFAICT it wouldn't change anything for those "most" users who don't need it.

Now I'm no react/webpack expert in anyway so there might be other technical issues (with Kyr's solution or anything similar) that I'm not aware of, but then why not just expose those issues (so someone - possibly me or someone from my team FWIW) has a chance to come with a working fix that could be accepted) instead of assuming what CRA users really need ?

My 2 cents...

@andriijas
Copy link
Contributor

@BrunoDesthuilliers And where are everyone who are happy about the way it currently works and how many are those? :) Just to balance things up... I dont like guessing but most people probably just dont question why the bundled file names are named the way they are.

I think deactivating it has significant down sides and can lead to unwanted side effects compared to building something that reads the manifest file.

@BrunoDesthuilliers
Copy link

@andriijas I'm afraid I wasn't clear enough: I'm not talking about removing hashing, but about having an option to disable it (via a command line flag, envvar or config, whatever). IOW: keeping the exact current behaviour as default, but having an easy (and controlable) way to change it when necessary.

Oh and yes also: except for this point (and even despite this point) I am a happy CRA users, thank you guys ;-)

@FixRM
Copy link
Author

FixRM commented Aug 21, 2019

As far as I see, some people also have problems with v3 chunk/hashing schema. The option to disable this can be a rescue for them as well

@BrunoDesthuilliers
Copy link

Oh and yes, wrt/

most people probably just dont question why the bundled file names are named the way they are.

Well, they should, really - or, more exactly, they should not, because they should already know why those hashes are there. But it's not because some users don't understand why this feature is there or aren't even aware it exists that there's no perfectly legitimate use cases for allowing other users to disable it.

@danielimmke
Copy link

danielimmke commented Apr 9, 2020

The other Issue that was about this was closed a while ago but I wanted to add my own updated package.json that works with dropping the hashes out of a chunked file for people Googling:

"build": "react-scripts build && npm run rename-build-files && npm run replace-build-files-text",
"rename-build-files": "renamer -f '/\\.[^\\\\.]+\\.chunk\\./gmi\\' -r . 'build/**'",
"replace-build-files-text" : "replace-in-file '\/\\.[^\\\\.]+\\.chunk\\.\/g' '.' 'build\/**' --isRegex --verbose"

Uses the renamer package to actually change the filenames and replace-in-file to change the references.

The raw, unaltered commands (you have to escape them to put them in package.json) are:
renamer -f '/\.[^\\.]+\.chunk\./gmi\' -r . 'build/**'
replace-in-file '/\.[^\\.]+\.chunk\./g' '.' 'build/**' --isRegex --verbose

If you wanted to add query string cache busting you could probably write another line using the replace-in-file to do it.

@heyimalex heyimalex reopened this Apr 9, 2020
@RXminuS
Copy link

RXminuS commented Apr 28, 2020

Would love to see the ability to witch to query based hashes. That way logrocket would finally work correctly with our Netlify deploy https://docs.logrocket.com/docs/troubleshooting-sessions#styles-are-not-appearing-in-recordings

@rsomepalli
Copy link

If you're looking for a solution right now, there are definitely ugly ways to automate this using asset-manifest.json, which is a sort of mapping from the original names to the hashed names.

This does sound like the right way to me. And you could right an automated script that reads it, does something, and even share that script between projects.

lot of requests for this over the years, is it a technical issue that is difficult to fix or a disagreement on that it not needed

@TuureKaunisto
Copy link

We'd also appreciate the option to not add hashes to file names and use query strings or other methods to bust the cache instead so that when someone has an expired html file, they still get the js files instead of a blank page.

The janky workaround we ended up going with to solve this is serving the new bundle.js file even if the hash doesn't match.

@toabi
Copy link

toabi commented Mar 14, 2023

Here's a minimal working configuration for react-app-rewired which works for us:

module.exports = function override(config, env) {
    if (env !== "production") {
        return config;
    }

    // Get rid of hash for js files
    config.output.filename = "static/js/[name].js"
    config.output.chunkFilename = "static/js/[name].chunk.js"

    // Get rid of hash for media files
    config.output.assetModuleFilename = 'static/media/[name][ext]'

    // Get rid of hash for css files
    const miniCssExtractPlugin = config.plugins.find(element => element.constructor.name === "MiniCssExtractPlugin");
    miniCssExtractPlugin.options.filename = "static/css/[name].css"
    miniCssExtractPlugin.options.chunkFilename = "static/css/[name].css"

    return config;
};

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

No branches or pull requests