Breakpoint debugging minfied/mangled/compiled variables - javascript

Working on building JavaScript sourcemaps into my workflow and I've been looking for some documentation on a particular part of debugging source maps. In the picture below I'm running compressed Javascript code, but through the magic of source maps Chrome debugger was able to reconstruct the seemingly uncompressed code for me to debug:
However, if you look at the local variables, someNumber and someOtherNumber are not defined. Instead, we have a and r, which are the compiled variable names for this function. This is the same for both Mozilla Firefox and Chrome.
I tried looking through the Chrome DevTools Documentation on sourcemaps, but I didn't see anything written about this. Is it a current limitation of sourcemap debugging and are there any workarounds for this?
update:
I've since found this thread in chromium project issues. It doesn't look like it has been or is being implemented. This is becoming an increasingly more important problem as teams are beginning to implement Babel in their build systems to write ES2015 code. Have any teams found a way around this?

Using Watch Expressions on the right hand side, usually solves this.
Expand the menu, and use the plus button to add your variables.
You can use someNumber and someOtherNumber, and even someNumber + someOtherNumber.

Looks like it's been addressed and will become available in the next Chromium update

There's still no solution to mapping variable names in Javascript source maps, but there's a solution for Babel 6. As we've adopted ES2015, the mangled import names became a major pain point during development. So I created an alternative to the CommonJS module transform that does not change the import names called babel-plugin-transform-es2015-modules-commonjs-simple.
As long as you aren't writing modules that depend on exporting dynamic bindings it is a drop-in replacement for the default babel commonjs module transform:
npm install --save-dev babel-plugin-transform-es2015-modules-commonjs-simple
and .babelrc:
"plugins": ["transform-es2015-modules-commonjs-simple"]
This will compile ES2015 modules to CommonJS without changing any of the symbol names of imported modules. Caveats are described in the readme.
This won't help you with minifying/uglifying, though, so the best solution seems to be to just don't use minification during development. Then at least it's only a problem if you have to debug something on a production web site.

Related

Import, Require? How to Mash Javascript Files Together?

This is vague - I apologize in advance, I am trying to be as succinct as I can with my limited understanding, while exposing my potentially incorrect assumptions.
I have a website that's literally one huge HTML file. It runs scripts defined in-line in a <scripts> tag.
My goal is to move all the scripts into individual .js files and pull them into index.html (or into one another where required). I am familiar with the usage of Node's require and I am familiar with import, as used in Angular. I stress usage because I don't really know how they work.
Assumption 1: I cannot use require - it is purely for Node.js. The reason I bring it up is that I am pretty sure I have seen require in AngularJS 1.5 code, so assuming makes me uncomfortable. I am guessing this was stitched together by WebPack, Gulp, or similar.
Assumption 2: I should use import, but import only works with a URL address, if I have my .js hosted on a server or CDN, it will be be pulled. BUT, I cannot give local pathing (on the server) here - index.html will NOT automatically pull in the dependencies while being served. I need npm/Webpack/other to pre-compile my index.html if I want the deps pulled in on the server.
Assumption 3: Pre-compiling into a single, ready-to-go, html file is the desired way to build things, because the file can be served quickly (assuming it's ready to go). I make the assumption with the recent trend of serving Markdown from CDNs, the appearance of the JAMstack, and the number of sites using Jekyll and such (though admittedly for traditional Jekyll sites).
Assumption 4: I also want to go to Typescript eventually, but I assume that changes nothing, since I will just pull in TS to compile it down to .js and then use whatever solution I used above
Question: If it's clear what I am trying to do and what confuses me, is a decent solution to look into npm/Webpack to stich together my .js files? What would prepare them for being stiched together, using import/export? If so, is there an example of how this is usually done?
As you mentioned, require cannot be used for your purposes, since it is a part of CommonJS and NodeJS's module system. More info on require can be found here: What is this Javascript "require"?
Import is a ES2015 standard JS syntax. But ES2015 standard and everything above it has very limited browser support. You can read more about it here: Import Reference
However, you can still code in the latest standard (thereby enabling the use of import/export etc.,) and then transpile the code to be able to run on the browser. Inorder to do this, you require a transpiler. You can refer Babel which is one of the most popular transpilers : https://babeljs.io/
For your exact purpose, you need to use a module bundler. Webpack/Rollup etc., are some popular module bundlers. They can automatically identify all the JS files referenced through import, combine them and then transpile code to be able to run on the browser (they also use a transpiler) and produce a single JS file (or multiple, based on your configurations).
You can refer the getting started guides of Webpack: https://webpack.js.org/guides/getting-started/
or RollupJS: https://rollupjs.org/guide/en#quick-start

Webpack multi ES version builds

Hello you smart people of the Stackoverflow. I have a challenge on a webpack build I am trying to set up.
What I am trying to acheive
I am trying to create a build that generates two version of my JS files. One that uses ES 6/7+ which will be used by the latest browsers and one that is transpiled back to ES 5.
The reason is that I want to minimize code sent to the "decent" browsers and to leverage any performance optimizations that can be drawn from using pure ES 6/7, not to mention adding less polyfills to the code.
The problem
Currently I have achieved my goal by running two parallel builds; one that transpiles the code with only few Babel transforms for a ES 6/7+ version and a second that uses the es2015 preset to transpile back to ES 5 and this generally works as intended. However my problem is that the full build that transpiles both versions is SUUUUUPER slow. We are talking 5+ min slow which is far from ideal.
One of the problem I see right away with this setup is that there is a lot of code that is being reparsed that might not need reparsing, such as CSS (stylus), images, SVGs, fonts etc. All of these assets really only need to be treated once, as it will be exactly the same for each version of the JS files. So in reality I only need to transform the JS part of the code, which is why I created the rebabel-webpack-plugin module, which really just takes the emitted files, transpiles them again and save the code under another name. This works fine, but it feels hacky and it kinda circumvents the original webpack build flow with some possible drawbacks as a consequence:
I don't really think that SourceMaps will be working properly, as it is not transpiling the original code.
Adding polyfills with a babel-preset-env babel-polyfill combo could be challenging and/or hacky
Bundle analyzers could be messed up
Unable to do a shared code file for regenerated files
I have not verified these drawbacks, but they are what I can see of immediate possible issues.
I have tried running a subsequent build on the emitted files, which works, but generally it is kinda the same as using the rebabel-webpack-plugin, but with a more awkward setup (collecting list of emitted files -> setting up new config -> run new build).
The actual question
So my question for you bright minds out there boils down to: How do one achieve a proper "re-targeting" of our JS files using webpack, without having to run two parallel builds?

Is it possible to configure different JavaScript language versions for different files?

I'm using WebStorm 2017.1.4 and I have a project which contains both ES5 and ES6 files at the same time. Therefore I want to configure syntax highlighting accordingly, but I'm unable to find how to do it :-(
So, the question is: how to configure JS version per file or, at least, folder?
So, the question is: how to configure JS version per file or, at least, folder?
ATM it's not possible. But such functionality will be available in 2017.3.
In meantime -- have a look at some possible workarounds in corresponding ticket (they might help in rather limited number of cases) -- https://youtrack.jetbrains.com/issue/WEB-12666.

Typescript and React outputting require

I'm trying to get Typescript and React working together in MVC Core
The problem is the requirement for the following lines in my .tsx file:
import React = require('react');
import ReactDOM = require('react-dom');
These lines pass through both compilers becoming the following in the JS for browser processing:
var React = require('react');
var ReactDOM = require('react-dom');
Obviously, the browser cannot run these lines, because "require" is not a function in the browser
And yes, I can verify that both Typescript and React have processed the file.
Elsewhere on the site, it is suggested to use a global import, however this is a bad idea (it even says so in that post), I could also fix this by creating an empty function called "require", but that would also be bad practice
That this situation has arisen at all I find surprising, I thought the whole point of TypeScript was to take better code that the browser doesn't understand and transform it into equivalent code that it would. Thus, that TypeScript has allowed these lines to just pass through is baffling to me.
I have tried using the module directive in tsconfig.json to produce the required output, however there doesn't seem to be a browser compatible option
Is there a way to get React's babel compiler to eat the require functions? Has Typescript left them in because it expects React to do something with them?
EDIT: My question is different from the one suggested as a duplicate because it asks about module() and not import.
Though I suspect the answers to the 2 questions may be the same, suggestions on the accepted answer such as "just us a reference" don't work and although use of an external module loader should solve the issue, it's a broken solution
require() is not a part of browser based JS, therefore I don't want TypeScript to output it at all
EDIT2: Since more details of my setup have been requested, here you go:
The structure of my wwwroot/js directory is as so:
/def
..react.d.ts
..react-dom.d.ts
tsconfig.json
source .tsx and compiled .js files
Note that the d.ts files are copypasta from the repositories. There doesn't seem to be a way to load them in "properly" without adding ridiculous dependencies to the project such as node. NuGet modules that seem to do this in regular mvc have no functionality in mvc core
I've also tried moving the d.ts files to be in the same folder as everything else, this has no effect
tsconfig.json looks like this:
{
"compileOnSave": true, //Doesn't do anything? Build required to compile
"compilerOptions": {
"noImplicitAny": false,
"noEmitOnError": true,
"removeComments": false,
"sourceMap": true,
"target": "es5", //Is this the ES version I'm supposed to be typing in or the ES version to compile to? Irrelevant, changing this does nothing
"jsx": "react" //Using "preserve" outputs a jsx file to go through the React Babel compiler, does not solve issue
//"module": Irrelevant, a "don't worry I've got them covered" flag option doesn't exist, no options are suitable for browser use
//"noResolve": Irrelevant, does nothing
},
//"files":[] Explicitly including the d.ts files here doesn't seem to do anything, does not allow me to remove import lines
"exclude": [ //Have tried removing this, doing so has no effect, does not allow me to remove import lines
"node_modules",
"wwwroot"
]
}
Since I'm using Visual Studio everything compiles on build, I assume it's using tsc.exe under the hood
As for React... I have the following listed in the dependencies section of project.json
"React.AspNet": "2.5.0",
"React.Core": "3.0.0-rc1"
In startup.cs I have the following in ConfigureServices:
services.AddJsEngineSwitcher(
options=>options.DefaultEngineName = V8JsEngine.EngineName
).AddV8();
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
services.AddReact();
...and the following in configure
app.UseReact(config => {});
For development purposes I have the following in my _Layout.cshtml
<environment names="Development">
<script src="https://unpkg.com/react#15.3.2/dist/react.js"></script>
<script src="https://unpkg.com/react-dom#15.3.2/dist/react-dom.js"></script>
</environment>
This is a learning project so it won't go to production mode, but if it did I would self-host the react source code and put it through the default bundler for bundling and minification. I don't believe that the positives of using a cdn outweigh the risks
I have tried using /// references, they seem to be a deprecated feature and in this case they don't do anything
I have tried using the following syntax to import react, but this also leads to different non-browser compatible code being output
import React = __React;
import ReactDOM = __React.__DOM;
It's important to note that both TypeScript and React work completely under these conditions on their own, no node dependency, no silly packing thing. It is only the TypeScript module system that insists on outputting things I don't need
Right so... after much much researching, my conclusion is that MVC Core, TypeScript and React shouldn't all go together just yet.
A lot of documentation and discussions hint at some sort of implicit referencing that's possible, and that seems to be the preferred way forwards when your project doesn't warrant a client-side module system, however... this feature doesn't seem to work with non-Typescript modules, or if it does it's so obscure and badly documented that I can't figure it out
....this could be one of those things where it's so obvious to everyone else that nobody bothers discussing it, if it is please let me know how stupid I am
The bottom line seems to be that if you want to use TypeScript's module system, you're supposed to have a browser-side module system that it can talk to.
I've looked over all of these and put a lot of work into understanding which is the best one for React and .Net
React places some extra constraints on this because you want to be using it's Server Side Rendering feature... like, you seriously want to be using that it's the best thing about React, so you need a module system that also plays nicely with it.
I've concluded that RequireJS is probably the right way to go for a number of reasons, for the client it's just 1 lightweight JS file, which compares nicely to the gargantuan JS behemoths of it's competitors, and it's own server side components have a .net version which should lead to an easier time making them work with React's server side stuff
....unfortunately RequireJS's server side components have a dependency on the old MVC for .Net Framework, so you can't use them in MVC Core yet, for now it's a dead end
Honestly, coming from a decade and a half of Javascript programming, I find this assumption on TypeScript's part that everyone is using a heavy client-side module system to be more than a little scary
I think it's important to remember that no matter what scripting you do for the browser, it all either runs in, or compiles back to, Javascript. This means that nothing you can bring in can possibly be more powerful than Javascript on it's own.
You use these things because they're quicker to code with, easier to test, show up errors at design time etc etc, i.e. they make life much easier for you and your team, but just like a box of pills, every single one of them has side effects and if you use too many they build up and cause problems
These module systems all look like great tools in the right projects, just like every "pill" in the "box" mentioned above, but I don't think they should be nearly as ubiquitous as TypeScript seems to assume they are
If you go for a small client stack that closely fits the needs of your project, and correctly segregate your JS into a global bundle, and a set of view-specific bundles your application can grow very large without encountering any of the issues that you want a heavy module system to solve
If you ever find yourself thinking you need such a thing, I would take the time to go back over your tech stack and really work out what each piece is doing for you and whether it's worth the cost to have it there, cutting that stack down is in many cases going to be a much better way to keep it stable than adding yet another framework to it
You've got to ask yourself what problems each tool is solving for you, whether it's successful in doing so, and if there's a better way... particularly one provided by another tool on your stack, a solution requiring no additional tools at all, or a solution provided by removing the tool that causes the issue as a side effect
I've seen a lot of people talking about these module loaders as a way to avoid clashes caused by adding things to the global namespace, and I'm sorry but moving all of those names to a module list so that they can clash there instead really doesn't solve anything
That in mind... webpack.... I think I jumped too early on the node dependency here, on taking a closer look I think it just uses node to compile things at design time, which is fine, as long as it doesn't want node on my production server we're cool but... all webpack is doing is taking your require lines and using them to inline other scripts, that's not what these lines are meant to be used for and using them in this way defeats the object of using them in the first place
All it seems to do is take the modules and dump them back into the global namespace where you didn't want them in the first place, furthermore if you're taking my advice above and making a global bundle, and one for each view that needs it's own tooling you're going to run into problems doing things the webpack way.... again, please correct me if I've misjudged this one
Well, that's the best answer that I can come up with for now, really hoping some people will show up and discuss it with me because it feels like I'm missing the point in a few places
For now I'm going to look into a bunch of React specific things and then maybe I'll see if I can get this stack working in MVC for Framework and see what changes
And if someone can come up with a better answer or a proper solution becomes available in a few months after the components have been patched a bit more then I'll move the green tick over
Obviously, the browser cannot run these lines, because "require" is not a function in the browser
Indeed. What tutorial are you following? You definitely need a module bundler in addition to TypeScript compilation e.g. here is a quickstart on webpack : https://basarat.gitbooks.io/typescript/content/docs/quick/browser.html

Comparison of methods to create a toolchain: JS modules / loader / build

In the process of evaluating the various approaches available to developers to use javascript modules, module loaders and build tools, i'd like some suggestions on what tools you use, and why.
I'm currently after something that is able to:
-encourage modular code
-allow features to be added based on necessity to a given module [think mixins/inheritance]
-produce a BUILD that contains a development release, and at the very minimum a production release with different layers (say, i want a layer [a script] which contains my bootstrap code, module 1, 2 and 3; and then another layer which contains modules 4,5 and 6. This way I can defer loading of code based on what's actually going on in the application.)
-Work [when built for production] in an extremely low bandwidth scenario, with xfer speeds of 1kbps and high latency (think worst case mobile connection over GPRS to get the picture).
I've seen the following:
Using prototype inheritance, as in:
myNS.thing = function(){};
myns.thing.prototype = {
something: "foo"
}
Which can be built by simply taking the contents of this script, and appending it to the next one one wants to include in a production optimized package as a single script. Loaders in this case are simple script tag injections/eval's or similar, based on a known file.
I've also seen other approaches, such as:
function(){
return function(){
something: "foo"
}
}();
Building this already gets more complex because one has to manipulate the script, removing the wrapping self executing function and combining the return values into one object. I am not aware of an "easy" way to use available build tools. The loader approach works the same as above.
Both of these approaches lack dependencies.
Then we have AMD:
define("mymodule", ["dep1"], function(dep1){
return {something: dep1}
});
Some might be nauseated by its indenting, and its "ceremony", but still its quite effective, the google closure compiler knows about it natively, it knows about dependencies, and seems to have widespread adoption across the board. There are a bunch of module loaders available for it (https://docs.google.com/spreadsheet/ccc?key=0Aqln2akPWiMIdERkY3J2OXdOUVJDTkNSQ2ZsV3hoWVE#gid=2) and quite a few build tools as well.
What other options do you know of, or have you seen used in production?
As said, i'm interested in a combination of code syntax, loader tools and build tools. These three must exist and be working together properly. The rest is an academic excercise i'm not interested in.
I personally use RequireJS, an AMD solution. If I'm whipping up quick proof-of-concepts I won't bother setting that up, but the most common source/dep-mapping solutions I know of now include:
RequireJS
CommonJS
Google Closure
YepNope (a conditional loader, can be used in combination with the others)
I have started a boilerplate that uses Require in combination with Backbone to get all the ugly setup code out of the way:
https://github.com/nick-jonas/assemblejs
So you can type assemble init to scaffold the basic project and assemble build to run the compilers and get a final production-ready build.
You might be interested in looking at Grunt a command line tool with various modules for building javascript projects. It uses npm for dependencies and it will work with amd modules, but you can just configure it to concatenate the files you need using grunt-buildconcat.

Categories

Resources