[00:14] The transpiler we're going to use is called Babel. We're going to use the Babel CLI to transpile using one of our npm scripts. We're going to run npm install, save dev, or protip npm i -D babel-cli. With that installed, we can see it in our dev dependencies here. We can now add a build script. We'll say build.
[00:37] Here, we'll use the Babel CLI that has been added to our node modules bin. We can see Babel there. Here, we can use Babel. We want our OutDir, the directory for the transpiled files, to be the dist directory, which Babel will create for us. Then, our input directory will be the source directory.
[00:58] Let's go ahead and run npm run build. It's going to run our files through Babel, and output those in our dist directory. However, we see that we have this index.test.js file in here. We don't want to distribute our test. There's no reason to do that. We're going to do add ignore*.test.js. This will tell Babel to not worry about anything that has .test in it.
[01:23] If we run npm run build, we're going to see that the index.test.js file is still in the dist directory. This is simple enough to solve because we can go ahead and delete that dist directory. We can rerun npm run build. We'll see that the test file is no longer in there. That's fine.
[01:46] However, as we build this library and add different files to it, we don't want to have to always remember to remove the dist directory. We're going to have another step in our build process to delete the dist directory before we run the build.
[01:59] Essentially, we want to run something before the build script runs. This is accomplished by simply adding pre and then the name of the other script. What I can do here is run rm -rf dist. If I run the build, npm run build, it's going to first delete the dist directory, and then recreate it. We can verify that by adding a fu.js in here.
[02:23] If I rerun that, it deletes everything and recreates the dist directory. However, this is not cross-platform. Rm -rf will only run on UNIX-based machines like Mac. Because I want this to be run on Windows for contributors who might be coming from Windows, I need to come up with a cross-platform solution. There's a package I can use to do this.
[02:45] We'll npm install as a dev dependency, rem. This package will basically allow me the same API that I can use. We can see that it's been installed as a dev dependency here. I can replace rm -rf with rem -ref. This is now a cross-platform.
[03:04] Now that we have our build running, let's go ahead and add some ES6 in our source. We can write these require statements into ES6 imports. Save that. We'll run our build, npm run build. Let's take a look at our output. We need to actually transpile something. Even though we're running things through Babel, we're not actually getting any transpilation.
[03:28] This is where transforms and presets come into play. By default, Babel doesn't actually do anything to your code. You need to explicitly list the transforms that you want to have Babel apply to your code. However, managing this list of transforms will be tedious. Babel has this concept of presets that include a bunch of transforms. We're going to use some of those now.
[03:47] We're installing the ES2015 preset, which includes all of the features available in ES2015, as well as the Stage 2 preset, which includes all of the features that are currently at Stage 2 in the standards process. If we look at our dev dependencies here, we'll see those installed. Now, we need to configure Babel to use these presets on our code that it's transpiling.
[04:08] There are a couple of ways that you can do this. We're going to go ahead and add it right in our package.json. With that, if we now run npm run build, and check out our dist, we're going to see that Babel is indeed transpiling our import statements.
[04:24] We need to go to our package.json and update domain to point to this new dist file, so that when people require starwars-names, they're going to be getting the transpiled version rather than the ES6 version. Then, we'll see that we have another problem.
[04:38] If we look at our index.js here, we are doing this simple require starwars-names.json. However, in our dist directory, there is no starwars-names.json. We need to copy this file over into the dist directory. Babel actually includes this feature as part of its CLI. We can simply add --copy-files, and save that. If we rerun the build, we'll see that the starwars-names is now included.
[05:06] There are still actually a few more things that we need to make sure of. First off, we need to make sure that before we run this publish script, we're going to run the build script. You might think that you can do the same thing to the publish script as we do to the build script. However, this pre-published script actually runs when people install our module inexplicably. We want to avoid doing that.
[05:30] We'll simply add this to our Travis build. Right after we run the test, we run npm run build. This will run before we do our semantic release. We'll be actually releasing the built version of our library.
[05:45] Now that we have everything ready to be built and then published to the registry, let's make sure that what is actually published to the registry is what we're expecting. We can test this out by running npm pack. This will create an archive file that we can open, and then explore. If we look in package, we now see npmignore, travis.yml, package.json, source.
[06:09] We see a lot of things that we probably don't need to actually distribute with our module.
[06:12] We can scope these things down in our package.json by adding a files property. It's an array of the files we want to have actually included. The only ones that matter is the dist directory and probably the readme.
[06:27] If we get rid of these files here, and then rerun npm pack, and open that archive file, we can see that the package now only contains the dist directory with our main file and the starwars-names.json file, package.json, and our readme.
[06:45] One final thing that we want to make sure that we do, let's go ahead and delete these files again. We definitely don't want to push those to Git. There's one other file we don't want to push to Git, and it's this dist directory. We'll go ahead and add that to our gitignore.
[07:00] Because that will be rebuilt every single time, we run the build locally. We don't want to actually commit that. By adding it to our gitignore, that's not going to be committed to GitHub, but it will actually be included when we publish to the registry, as we saw with the npm pack.
[07:17] To recap, to add ES6 support to your library, you simply need to install Babel CLI and the presets for the transforms that you want to include for your transpilation. Then, you configure Babel. You can do this in the package.json or as a .babelrc file. You specify the presets there.
[07:37] We added a build script that used Babel CLI to transpile our files in the source directory to the output directory of dist. We wanted to ignore our test. We wanted to copy the files over. As a pre-build stuff, we added rem -ref as a dependency, and deleted the dist directory.
[07:58] Every time when we run the build, we change the main to point to the dist/index.js, this new file that we're transpiling into. We also specified our files here to be a little bit more explicit about what it is that we're including in our package, specifically the dist directory being the thing that we're actually distributing.
[08:20] Finally, very important in the travis.yml, we specified that we run the build before we run our release to make sure that we are actually transpiling. That is what we published to the registry. That's how you add ES6 support to your module.
Hi Zack! I hope you're enjoying the series. Thanks for the question. Committing generated files to source control is a bad idea for libraries (I plan to write a blogpost explaining why). So what we've set up here is we release using semantic-release on Travis. But before we do that, we run the build which generates the dist directory. So at the time npm publish runs, the dist directory exists and people can require it in their projects. In a future lesson, I'm going to show how you can push these generated files to a
latest branch on GitHub. If you want to jump ahead, check out npm.im/. Good luck!
Thanks Kent. I learn a lot from this series.
Hi Zack, here's the blogpost I was talking about: https://medium.com/@kentcdodds/why-i-don-t-commit-generated-files-to-master-a4d76382564
Kent, thanks for doing this. I've learned a lot. Unless I'm mistaken, instead of babel, you will now need babel-cli and babel-preset-es2015 to get this working properly. At least that is the solution I've found.
Yes, this lesson has yet to be updated to Babel 6.
Just to clarify, was the solution for the dist issue to leave it untracked?
That's one solution, but you can actually do some things to make it more specific. I didn't talk about
.npmignore. If you use that, then you can add
dist to your
.gitignore. You can also add
dist to your
.gitignore and use
files in the
package.json. In retrospect, that's how I should have taught this concept.
Hi Kent. I want to ask why does test go before transpile? Shouldn't we test final form of our code?
Hey! Hopefully I answer it properly here: https://www.briefs.fm/3-minutes-with-kent/31
It helps, thanks!
Hey there Mr Kent C Dodds. I noticed that you use the webstorm ide as do I. I noticed you don't get funky warnings when you write es6 like I do. I get squigglies, highlights, warnings etc. I have tweaked what I thought it might be however I don't seem to be able to effect any change in the view. Could you point me in the right direction?
I don't use Webstorm anymore, but here's how you set your syntax to support ES6: https://medium.com/@brandonaaskov/enabling-es6-syntax-support-in-webstorm-48e22956ecfd
Something small to note: It's recommended to use
babel-preset-env in place of
babel-preset-es2015 (and other yearly presets) now. See https://babeljs.io/docs/en/env/. Simply replace
I don't understand why not commit dist folder. If someone wants to require this library, it can't require right?