3

TL;DR: How can I tell react build script to leave parts of code untouched?

I made an app with "create-react-app". I am using the standard "npm run build" command to make my production build.

In the index.html file I included a Google Tag Manager and Google Optimize snippet.

On build, the script minifies those in a way that prevents them from working.

So right now, every time I "build", I have to overwrite the minified parts with the original snippets manually. That is - of course - super unhandy.

How can I tell the build script to leave these parts alone? I browsed the docu without success...

Thanks for any help!

NORMAL (UNMINIFIED) CODE:

  <!-- Google Optimize async hide -->
  <style>.async-hide { opacity: 0 !important} </style>
  <script>
  (function(a,s,y,n,c,h,i,d,e){
   s.className+=' '+y;
   h.end=i=function(){
     s.className=s.className.replace(RegExp(' ?'+y),'')};
     (a[n]=a[n]||[]).hide=h;setTimeout(function(){
       i();h.end=null
     },c);
  })
  (window,document.documentElement,'async-hide','dataLayer',4000,{'GTM-ABCDEF12':true});
  </script>


  <!-- Google Tag Manager -->
  <script>
  (function(w,d,s,l,i){
    w[l]=w[l]||[];w[l].push({
      'gtm.start': new Date().getTime(),
      event:'gtm.js'});
    var 
     f=d.getElementsByTagName(s)[0],
     j=d.createElement(s),
     dl=l!='dataLayer'?'&l='+l:'';
     j.async=true;
     j.src='https://www.googletagmanager.com/gtm.js?id='+i+dl;
     f.parentNode.insertBefore(j,f);
  })(window,document,'script','dataLayer','GTM-ABCDEF12');</script>
  <!-- End Google Tag Manager -->

MINIFIED CODE:

  <style>.async-hide{opacity:0!important}</style>
  <script>!function(e,n,a,c,t,d,s,i,l){
     n.className+=" "+a,d.end=s=function(){
       n.className=n.className.replace(RegExp(" ?"+a),"")
     },
     (e[c]=e[c]||[]).hide=d,setTimeout(function(){
       s(),d.end=null
     },4e3)
   }(window,document.documentElement,"async-hide","dataLayer",0,{"GTM-ABCDEF12":!0})
    </script>
    <script>
    !function(e,t,a,n,g){
      e[n]=e[n]||[],e[n].push({
        "gtm.start":(new Date).getTime(),
        event:"gtm.js"
      });
      var m=t.getElementsByTagName(a)[0],
        r=t.createElement(a);
      r.async=!0,
      r.src="https://www.googletagmanager.com/gtm.js?id=GTM-ABCDEF12",
      m.parentNode.insertBefore(r,m)
      }(window,document,"script","dataLayer")
    </script>
sborn
  • 111
  • 1
  • 9
  • why would minifying prevent them from working? are you sure that's what's causing the error – azium Jul 11 '18 at 19:43
  • Thanks for the answer. It works when I paste the unminified version over the minified version. I edited the original post to show both codes. – sborn Jul 11 '18 at 19:56
  • The only difference that seems somewhat significant to me in the minified code is the comma instead of the semicolon after r.async=!0 - however that should be fine too, I think.. – sborn Jul 12 '18 at 18:48

2 Answers2

0

There is at least 1 major use case where not minifying code fragments is necessary, that is when code uses reflection. As an example, say you receive from an Ajax call a structure such as:

{
 "type": "SomeConcreteType",
 "fieldA": "Some value"
}

Your business logic may require that you create an instance of SomeConcreteType. In a non-minified world you would simply write:

var obj = new window[type]();

but in a minified world you can't because SomeConcreteType name has been erased.

Conversely, when sending an instance to the server, you can no longer rely on obj.constructor.name.

This leads to very ugly code, where you switch on hard coded strings.

Having to eject for just this doesn't sound right.

Not sure why CRA scripts cannot load some config files to override the values in the default ones...

Rabbid76
  • 202,892
  • 27
  • 131
  • 174
-1

Check out ejecting the config, this should allow you to customize how it compiles your assets.

npm run eject Note: this is a one-way operation. Once you eject, you can’t go back!

If you aren’t satisfied with the build tool and configuration choices, you can eject at any time. This command will remove the single build dependency from your project.

Instead, it will copy all the configuration files and the transitive dependencies (Webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except eject will still work, but they will point to the copied scripts so you can tweak them. At this point you’re on your own.

You don’t have to ever use eject. The curated feature set is suitable for small and middle deployments, and you shouldn’t feel obligated to use this feature. However we understand that this tool wouldn’t be useful if you couldn’t customize it when you are ready for it.

https://github.com/facebook/create-react-app/blob/master/packages/react-scripts/template/README.md#updating-to-new-releases

Brandon Korenek
  • 167
  • 3
  • 14
  • Hey Brandon, thanks for the answer. That seems to be a quite brutal method and quite frankly something I wouldn't dare to touch yet. – sborn Jul 12 '18 at 18:42
  • Seems to be somewhat obstructing to future updates too, no? I am looking for a way like in eslint where you can put comments around parts of the file so these parts stay untouched. That to me seems somewhat more lightweight than the eject option :/ Any idea? – sborn Jul 12 '18 at 18:50
  • It is, and does make future updates difficult. Isn't this code going directly into the HTML? Have you tried puting everything into a file outside of the index.html and linking to it? I didn't even realize it minified the index.html honestly. – Brandon Korenek Jul 13 '18 at 15:22
  • Using an external file is something I will try! Good idea! – sborn Jul 16 '18 at 14:22