Hi all, I found some interesting Webpack features so I'd like to share them. Excluding Code ============== Sometimes it is useful to behave a bit different in a development build and in the production build. For example you might add some extra debugging in development mode or you might use some development library which does not make sense in production. For example the patternfly-react-seed project[1] which is a template project for the PatternFly library uses the "axe" accessibility testing engine [2]. Of course, reporting the potential accessibility issues only makes sense for developers in the development builds. You can do that with code like: ``` if (process.env.NODE_ENV !== "production") { const axe = require("@axe-core/react"); axe(React, ReactDOM, 1000); } ``` That looks pretty straightforward isn't it? But it is actually quite tricky because 1) you cannot access the environment from browser Javascript, 2) even if that worked it's running on a completely different machine. So how it works actually?? The trick is that Webpack replaces (!) the "process.env.NODE_ENV" coode in the source code with the current value when processing it. So what the browser actually sees in the development mode is: ``` if ("development" !== "production") { const axe = require("@axe-core/react"); axe(React, ReactDOM, 1000); } ``` And that condition is always true so that code always runs. In the production mode it would be: ``` if ("production" !== "production") { import { foo } from "foo"; foo.bar(); } ``` So that would never run. But the production builds usually use extra minification and optimization step. The minifier is quite clever and for example it removes the always false conditions from the code completely. So the final minified production code is reduced to: ``` ``` Yes, nothing! :-) By default it works only for the "NODE_ENV" variable but you can add support for any other environment variable using the Webpack EnvironmentPlugin, see [3]. Replacing Values ================ This is similar to the previous case, but instead of replacing an environment variables you can replace any value at the compile time. For example you want to somewhere display the project version or the last git commit hash or the build date or... (Um, the build date is actually a bad idea, that would break reproducible package builds in OBS.) Weback has DefinePlugin for that, see the documentation [4]. If you want to replace a string then it must be quoted because the value is replaced literally. A common trick is to use JSON.stringify(string). On the other hand that allows the replacement to be any expression, even some code to execute. The ESlint step is called *before* these string replacements so it sees the original code. And that means it would complain about undefined variables. The workaround is to define it as a known global in the .eslintrc.json configuration file [5]. HTH, Ladislav [1] https://github.com/patternfly/patternfly-react-seed [2] https://github.com/dequelabs/axe-core [3] https://webpack.js.org/plugins/environment-plugin/ [4] https://webpack.js.org/plugins/define-plugin/ [5] https://eslint.org/docs/latest/use/configure/language-options#specifying-glo... -- Ladislav Slezák YaST Developer SUSE LINUX, s.r.o. Corso IIa Křižíkova 148/34 18600 Praha 8