Tag Archives: gulp

Control Add-ins Supercharged: Debugging with source maps

So far I’ve shown how to configure gulp to help you with some basic JavaScript development tasks, such as bundling and minifying, and how to automate builds on every source file change. Let’s now take it to an entirely new level: debugging.

If you ever tried to debug your control add-in source code using Visual Studio Code, you might have realized two things: first, that it’s actually pretty simple to do; and second, that it’s not the kind of debugging that you want.

Let’s see why that is.

First, using VS Code with a browser such as Chrome, Edge (especially “Canary”, mmmm) or Firefox is easy. There are debugging extensions built for that purpose that allow you to either launch a browser with VS Code attached as a debugger, or to attach VS Code to a running instance of a browser (some browser configuration needed beforehand). However, when you use VS Code as a debugger like this, it’s hardly more than a glorified browser built-in developer tool – the only benefit of using VS Code is that, well, you are in VS Code, rather than inside the browser. However, you are not really debugging your source files – you are debugging scripts currently loaded in the browser. You can’t set debug breakpoints in your source files – you can only set them in copies of files that are loaded by the browser. If you catch a bug (kind of a point with a debugger) you can’t stop the process and immediately change the line where the bug is, but you have to first locate the matching source script, and then the offending line, and then fix it there. Not exactly a fun pastime.

And that’s annoying enough if you have a single script to work with, but if you have several scripts, bundled together, then minified, well, good luck with that. Debugging minified code is as close as you can get to inquisition-level torture in this century.

So, let’s fix this mess, and let’s enable debugging as it should be – let’s enable debugging of actual source files with full breakpoint integration and all.

That’s what my next branch is about. In it, I introduce source maps and how you can use gulp to build them. And then I explain how you can configure your VS Code to debug your source files.

So, head over to https://github.com/vjekob/supercharged_01/tree/06-gulp-debug and check out some pretty cool stuff.

Control Add-ins Supercharged: Automating gulp.watch

Yesterday you’ve seen how to use gulp to make it do something truly useful: bundling your JavaScript and CSS files. Introducing gulp for the purpose of bundling your files allows you to split your functionality into as many files as you want, but use only a single script and a single stylesheet file from your control add-in. That way you not only optimized how your browser loads the files, but you also eliminated the need to maintain your controladdin object file every single time a new JavaScript or CSS file is added (or an existing one is removed).

However, you still need to run gulp build every single time you want to build your bundles. If you forget that, your controladdin will not be updated with your changes.

Thankfully, gulp has an answer to this: the gulp.watch feature. That’s the topic of my next demo, that I’ve explained in the 05-gulp-watch branch of my supercharged-01 repository.

The Readme.md file of that branch explains how to configure the watch task in the gulpfile.js file, and how to configure VS Code to automatically run the watch task every time you open the workspace. Once you follow those instructions, you can work on individual JavaScript or CSS files without the need to run gulp build or to maintain your controladdin object file. The former is taken care of by gulp, and the latter is taken care by… well, gulp too. Gulp is cool, really 😎

Control Add-ins Supercharged: Teaching gulp some useful tricks

My last demo introduces gulp, an amazingly simple task automation tool. You’ve seen what it is, how to set it up, and how to create a simple hello-world task. Now it’s time to teach gulp some useful tricks and make it automate the “build” process for the JavaScript and CSS files.

The first demo in this series uses a single-file approach, and there I stated that it’s a bad thing to develop like that. It’s bad to put all the functionality in one single file. However, that rule applies for development, not for runtime. Your browser actually prefers using a smaller number of JavaScript (or CSS) files. That’s why typical runtime JavaScript libraries are bundled. On top of bundling, you’ll also want to minify your JavaScript and CSS files to make them as small as possible, to further improve the download and initialization speed.

These are the things that today’s demo uses. So, head over to the https://github.com/vjekob/supercharged_01/tree/04-gulp-useful branch, and check out how to configure your gulp to build your JavaScript and CSS bundles from your source files.

Control Add-ins Supercharged: Hello, gulp!

Get ready for the next big step in taking the control add-in development to the next level. Today, I am (re)introducing gulp.

I’ve blogged about gulp in the past, but I’ve never really finished that series. Life and work got in the way. But while I may not have blogged about it much, it’s been my companion for quite some time now, and now I want it to become yours, too.

In previous “Control Add-ins Supercharged” examples we’ve mostly explored how not to do things. Now we are ready to take a look in the opposite direction and start talking about how to do do things.

For this example, I’ll use my next demo branch 04-gulp-hello-world that you can check out here: https://github.com/vjekob/supercharged_01/tree/03-gulp-hello-world.

I don’t intend to copy/paste all the theory explained in the branch’s Readme file, but I’ll just say what you can find there:

  • Steps to install the prerequisites to run gulp
  • Steps to install gulp and make sure it works
  • Examples how to run gulp tasks from both command line and VS Code
  • Just a tiny little bit of theory around Node.js packages
  • A few good practices around some Node.js artifacts that will appear in your workspace once you install gulp

And with this small example that introduces gulp I conclude the introduction into the “Control Add-ins Supercharged” series. All the next steps will deliver ready-to-use stuff that you can plug into your own control add-in development process, and we’ll start building our toolchain step by step.

Have a great weekend!

Using gulp plugins to transform files

In the last post, I explained how to use tasks, but I didn’t explain yet how to make them useful. Tasks are most useful when they automate certain file operations, and gulp helps with reading and writing files. However, if you need to perform a transformation, then you need to look for plugins that can get that work done for you.

In this post you’ll learn how to set up and use various plugins that can automate some common file operations.

As gulp documentation says: Gulp plugins are Node Transform Streams that encapsulate common behavior to transform files in a pipeline – often placed between src() and dest() using the .pipe() method.

Let’s imagine that:

  • You are creating a control add-in and you are writing a lot of JavaScript
  • You want to isolate your JavaScript features into individual files, one file per feature, and that you want to combine these files all into one file that will be included in your control add-in
  • You want to write modern JavaScript, but still want to make sure all browsers will be able to run it (remember, anybody using earlier versions of Windows than Windows 10, and using the NAV/BC universal client, will be running Internet Explorer in there)
  • You want to minify the resulting file to consume space
  • You want to zip the contents of your control add-in into the Resource.zip file

All valid assumptions, correct? If you are anything like me, this is what you do every day.

Now, some of these things can be done manually, some not really, but all of them certainly can be automated using gulp. Our job would need to contain the following transformations:

  1. Bundle JavaScript files into a single file
  2. Transpile that file into a lower version of JavaScript
  3. Minify that file
  4. Package the contents of the resource directory to produce the Resource.zip file

The more astute of you will immediately notice that all of this cannot be one task. Unless you want to complicate your life, one task should only perform those operations that can be handled with a single pipeline. A single pipeline is what starts with a stream of input files and transforms them until you cannot transform it. This means that as long as the output of the previous operation can be the input into the next operation, you can pipe that output down the pipeline. Packaging the contents of the resource directory is an operation that cannot use the output of the previous operation, so you need to isolate it into a separate task.

Another reason why you may want to separate operations into individual tasks is when an operation makes sense on its own. If you can imagine any of the previous operations as something you’d ever want to run individually, then that operation should also be isolated into a separate task. Tasks can be combined in different ways, and I’ll address that as well in one of the future posts, so don’t be afraid to split up operations that can benefit from splitting.

In my example, packaging the Resource.zip file is an operation that can be done independently of everything else. JavaScript is not the only content of the resource file: you may change CSS, you may add or modify images, configure the manifest, you name it. In all these situations, you may want to package the resource file independent of the JavaScript operation. It just makes sense to turn it into a task of its own.

Good, so we have two tasks then, with the following flow:

  1. Preparing JavaScript file
    1. Collect all JavaScript files into a single stream
    2. Pipe that into a function that combines all the files into one
    3. Pipe that into a function that transpiles your code to a lower version
    4. Pipe that into a function that minifies your code
    5. Store the result into a destination inside the resource subdirectory
  2. Zip the content of your resource subdirectory
    1. Collect all files underneath the resource subdirectory into a single stream
    2. Pipe that into a function that zips the content of the stream
    3. Store the result into a destination directory

Good. Now that we know what steps we need to do, let’s create the two tasks with minimum operations that gulp can do on its own:

So far, so good.

Let’s focus now on JavaScript task first. The first operation we need to do on the files is to bundle (or concatenate) them. If bundling the files was the only operation you need, then you wouldn’t really need a plugin as Node.js contains all the necessary APIs for that. However, if your bunding is just a pass-through operation in a pipeline, you’ll need a plugin. Let’s look for a plugin.

Normally, you’d do a general google search, but gulp maintains its own plugin directory which makes your life much easier. Go to https://gulpjs.com/plugins/ and search for “concatenate”, you’ll find a number of plugins. For my example, I chose gulp-concat. When I need a plugin, I look in its documentation to see whether it can do everything I need, and how simple it is to use. I also look at its github repository (all of plugins I used have a github repository) where I can see how much “alive” it is: how many commits and how often, are there pull requests merged into it, how many forks are out there, is the author responding to issues, etc. All of it can contribute to a perceived reliability rating that finally makes me choose one plugin over another.

Good. Now that we know that gulp-concat plugin can do the job for you, how do you use it?

If you remember the first post in the series, you can remember how you imported gulp itself into your workspace: by using npm. Gulp plugins are typically package, and to import them into your workspace, you’ll also use npm. Just remember, any gulp plugin packages that you import are dependencies in your development environment, therefore you must use the –save-dev option. Let’s import gulp-concat:

Now that gulp-concat is a part of your solution and under the management of npm, you can use it inside your gulpfile.js script:

Now, we can use the concat in the pipeline like this:

The next step is to transpile that using babel. Again, a little search should help you find the gulp-babel plugin that you can then first install into your workspace. However, if you simply use this, you may realize that it does not work.

Some plugins use other packages that they don’t bundle directly, but allow you to choose specific versions of those packages, and sometimes they will provide different install scripts. To install gulp-babel with the necessary dependencies, you should use this:

… then declare inside the gulpfile.js script:

… and finally pipe the concatenated file into it:

Good job! Finally, we are ready for the last step of the first task – the minification. A quick search should reveal any number of possibilities, but I’ll go with this one:

When it’s installed, declare it:

… and then pipe the transpilation results into it:

And you are finished. If you did everything correctly, this is now your first task:

For the second task we need to locate a plugin that can zip a stream of files. Again, search the gulp plugin catalog, and you should discover gulp-zip. You are an expert by now, so you know that you first need to install it:

… then declare it:

… and finally use it in your zip pipeline:

If you did everything correctly, this is the second task:

Perfect. The only thing that’s missing is exporting the tasks from your gulpfile.js:

You can try to see if these two tasks now work:

Take a look inside your resource/Script directory and you should fine the controlAddIn.js script in there.

Then, run this:

Now take a look inside the build directory and you should fine the Resource.zip file in there.

Cool, but now we need another task that first invokes the javaScript task and then the resourceZip task in sequence. Luckily, gulp helps with that, too. The gulp.series() method creates a task that runs specified tasks in a serial sequence, one after another. Just export one more task from your gulpfile.js:

If you now delete the files that previous two tests created, and then run this:

… you will see that it has correctly built your Resource.zip file.

Just in case, here’s my latest state of the gulpfile.js:

In my next post, I’ll cover two more topics: deploying the control add-in to an NAV / Business Central instance using PowerShell from a gulp task, and passing configuration to gulp tasks from JSON configuration files.