Object.freeze during development - javascript

Please see the code here
if (process.env.NODE_ENV !== 'production') {
if ('function' === typeof Object.freeze) {
Object.keys(self._routes).forEach(function freezeRoute(name) {
var route = self._routes[name];
Object.freeze(route.config);
Object.freeze(route.keys);
Object.freeze(route);
});
Object.freeze(self._routes);
}
}
why do freeze in non production mode. Is it to verify it is not being modified during development, but avoid any kind of runtime cost during production?

Yes, this is precisely the reason mentioned in the commit where this functionality was added:
We use Object.freeze to freeze the router and route objects for non-production environments to ensure the immutability of these objects.
For production environments, it is recommended to use tools like envify along with uglify as part of your build process to strip out the [non-]production specific code for performance benefits.
We use if (process.env.NODE_ENV !== 'production') to wrap around Object.freeze(), so that you can use various tools to build the code for different environments:
The reason they did this was because Object.freeze was slow at the time - at this point the performance hit of Object.freeze has been greatly mitigated (at least in V8).

Related

How to make a JavaScript library which can work with Browser, NodeJS and Single Page Applications (React etc.)

So what I want to ask is: Is there a way to convert this simple file into a library which can work with Browsers (script tag), Node JS and Single Page Applications using single codebase?
Until now, all I have been doing was using libraries but it never came to my mind that it isn't actually that simple to make one. I am working on a React application where I created a simple helper file with exports. I thought "why not make it an independent library in NPM?". Just as I started testing it independently in NodeJS environment, I came to realize that there is actually a lot of difference in the way both environments make imports.
I have slight knowledge of Webpack, but I don't know how to approach it. Would I need different codes for different environments?
Another thing that confused me was when I thought about "How do we actually import things/functions from libraries?" Like when we install any library from NPM INSTALL and we do "import { abc } from 'library'", does it look for an index.js file in the library folder or what? Or in case of Node, "let lib = require('library')", where it does it look since its a different environment than SPA?
In conclusion, I have a simple single file I want to launch in NPM as a library which could work in any environment.
This is a very broad question, so a very broad answer: Look at tools like webpack, rollup, and browserify which are often used to make Node.js things available in the browser.
Another possibility is to look at how a module like slug is coded such that it works in the browser and in Node.js, but requires some hacks (and a decent test setup) to do it. For example, it checks typeof window !== 'undefined' to switch between code that needs to run in the browser vs. code that needs to run in Node.js. And this bit at the end detects the module system being used and acts accordingly:
if (typeof define !== 'undefined' && define.amd) { // AMD
define([], function () { return slug })
} else if (typeof module !== 'undefined' && module.exports) { // CommonJS
module.exports = slug
} else { // Script tag
root.slug = slug
}

Can i minify without uglifying with webpack

What I want to do is simple: I want to minify my code without uglifying it. I want to do this because am building a node module which I need to use in different environments.
My configuration is simple and standard. I just don't know how to minify without uglifying.
This is what I got:
Files:
src
- index.js
- Dog.js
dist
- main.js
webpack.config.js
module.exports = {
target: 'node',
mode: 'production',
};
index.js
const Dog = require("./Dog");
module.exports = {
Dog
}
Dog.js
class Dog{
//Typical Dog stuff
}
module.exports = Dog;
According to the next link minifying does increases performance.
Does it make sense to minify code used in NodeJS?
Per request of the OP, rounding up the comments in an answer.
For the reader, I think it is important to clarify that even though Javascript is widely (and correctly) known as an interpreted language by nature, browsers and certain other platforms compile it to native code for performance reasons. Read more about it here. Node.js is also built on V8 ==> What is the relationship between Node.js and V8?
The reason, it is common practice to minify client side code is because those files are transfered over the wire which is where we have significant overhead. Whereas for the server side code, the file size will only effect the compilation time.
There used to be a spec in V8 that hard stopped inlining function if the function body was longer than, I believe 600 characters, but this has been removed post Node 8.3+. See kibubi's answer in this question to see the commit that removed this limit:
Does removing comments improve code performance? JavaScript
You can read more about the new V8 optimizations here

Does webpack remove this type of code automatically?

This is a good helper for development mode, but does this code get removed from bundles or is a particular plugin needed to remove it? Seems like it would have to be removed since process is not available in the browser. What setting causes this to happen?
The webpack docs aren't really all that clear about what these options do, just giving vague references:
https://webpack.js.org/concepts/targets/
and
https://webpack.js.org/concepts/output/
if (process.env.NODE_ENV !== 'production') {
if (typeof nextValue === 'undefined') {
console.info(next);
throw new Error('React Table: A reducer hook ☝️ just returned undefined! This is not allowed.');
}
}
process.env.NODE_ENV is actually available in the browser because Webpack creates the process variable as a global in code that is output. It is controlled via the Webpack configuration mode.
You can set the mode in your config or the command line. If you use enivornment based Webpack configs (ie. webpack.dev.js, webpack.prod.js) they will automatically set the mode.
webpack --mode=production

Debug logging with React

I'd like to:
insert debug logging statements into my code that I want to be able to turn on and off during development; and
then have these statements stripped out entirely in production.
To accomplish stripping out the logs for production, I've seen that the React project itself uses this idiom:
if ("production" !== process.env.NODE_ENV) {
// warn or log or whatever
}
By compiling the modules with process.env.NODE_ENV set to "production" and then running the bundle through a dead code eliminator like UglifyJS, the logs will be eliminated as unreachable.
This is fine, but are there more flexible solutions? I'm thinking something like the debug() Node module, or really some even more powerful, like the Java logging APIs.
I am wondering why I'm not finding a module that combines the ("production" !== process.env.NODE_ENV) approach with debug().
var debug = function(msg) {
if ("production" !== process.env.NODE_ENV) console.log(msg);
}
module.exports = debug;
Usage:
var debug = require("debug");
debug("some logs");
Sorry, I couldn't help myself ;). But really, there are plenty of JS logging frameworks out there (although I honestly think the solution above is simple enough that you don't need to over-complicate things).
Coming from a Java world, I was pleased to see there is a 'log4javascript' project.
http://log4javascript.org/
It has some cool stuff including a logging console with some features...

What is the point of obvious ifs in reactjs source?

I found that the source code is full of comparisons if ("production" !== "development").
For example (from https://cdnjs.cloudflare.com/ajax/libs/react/0.12.2/react.js, line 6240):
if ("production" !== "development") {
this._checkPropTypes(
contextTypes,
maskedContext,
ReactPropTypeLocations.context
);
}
But why? The result of such checks is always the same.
They use browserify with envify.
envify will replace your environment variable checks with ordinary
strings - only the variables you use will be included, so you don't
have to worry about, say, AWS_SECRET_KEY leaking through either. [...]
By running this through a good minifier (e.g. UglifyJS2), the above
code would be stripped out completely.
This is done to enable development-only checks and logging.
If you look through the React source, you'll see if (__DEV__) checks, which get replaced with if ("production" !== process.env.NODE_ENV) by React's build process.
envify is then used to replace references to process.env.NODE_ENV in the source with its current value at the time the build process is run.
For the uncompressed development build of React (and when using the npm version, by default) process.env.NODE_ENV is set to "development", so you get the benefit of these extra checks, such as validating props passed to component against its propTypes, warning if controlled components are potentially read-only due to misconfiguration, warnings about lists of items without a key prop and all the other development-mode logging React provides for common problems such as misspelt lifecycle method and HTML attribute prop names.
For the compressed production build, process.env.NODE_ENV is set to "production", so when the build is compressed with UglifyJS, these blocks of code are detected by Ugilify's dead code elimination process as code which will never get run and are completely removed from the source.
A nice side-effect of this is that you can take advantage of if ("production" !== process.env.NODE_ENV) checks to add development-only checks and logging to your own React components and libraries, since people bundling React from npm currently (with v0.12.2 the current version at the time of writing) have to deal with this as part of their build process.

Categories

Resources