Babelify the files in place, in multiple directories - javascript

How can I use babel to transpile the JavaScript files containing ES6 stuff, in different directories? I want the result to be in the same directories (e.g. having foo/bar/index.js, I want to get the ES5 code in the same file, by overriding it).
To override one directory I use:
babel lib/ -d lib
This works for one folder (overrides all the content in the lib directory).
How can I do the same for two or more directories? For example, how can I do that for lib/ and bin/?

AFAIK the babel CLI isn't complex enough to support this use-case in a single command. However you could concatenate two commands to achieve the same result:
babel lib/ -d lib && babel bin/ -d bin
Or you could write a script that does this for you, using gulp or another build tool of your choice. For example (untested):
gulp.task('default', () =>
gulp.src(['bin/**/*.js', 'lib/**/*.js'], { base: './' })
.pipe(babel())
.pipe(gulp.dest('.'))
)

The codemod CLI is perfect for this.
It will just modify your files in place:
codemod --plugin babel-transformer.js src/**/*.js

Related

Babel-CLI set config value correctly

I am trying to add a build command that uses babel CLI to transpile my ES6. I am having difficult pointing it correctly to babelrc.
The file structure is roughly as follows:
root
src
index.js
...
.babelrc
.package.json
In my package.json, I originally tried the following:
"scripts": {
"build": "babel --out-dir dist src",
...
},
But this gave an error because of the array destructuring notation I have used in my code. I think this is because it is not picking up my .babelrc file. Using
babel --presets=#babel/preset-env --out-dir dist src
instead fixes this problem. But I would rather I didn't have to specify plugins etc. here and rely on the .babelrc file instead.
From reading this issue, I get the impression babel looks for a config file in src rather than root . Looking at the documentation it seems there is an option for specifying a config file, but I can't quite get it to work correctly. My attempt:
babel --config-file .babelrc --out-dir dist src
You can use ./node_modules/.bin/babel in place of babel.
Worked for me this week.
Check point 3 in the overview from babel-cli
https://babeljs.io/docs/en/usage
And running this command to compile all your code from the src directory to lib:
./node_modules/.bin/babel src --out-dir lib
You can use the npm package runner that comes with npm#5.2.0 to shorten that command by replacing ./node_modules/.bin/babel with npx babel
For Babel version 7.x, it looks for project-wide configuration in the file with name like this - babel.config.{json|js|cjs|mjs}. Check the documentation here.
In my end,
npx babel src/ -d lib/
Babel should already pick up the .babelrc file automatically. If you want to add that preset, you should specify
{
// ... more .babelrc up here
"presets": ["#babel/preset-env"]
// ... more .babelrc down here
}
in your .babelrc file.
But babel will automatically search for the closest .babelrc file in the directory starting at the entry file and working its way upwards (specified here at the bottom).

How can I run gulp with a typescript file

Have a gulp project that uses a gulp.js file but my project is in typescript so I'd rather have a gulp file in typescript. It would be possible to break the process into two steps where I:
1. Manually transpile the typescript gulp file into js, then
2. Call gulp <some-task-name>
But that doesn't seem optimal. Is there any better way of doing
this?
From Gulp docs for transpilation:
Transpilation
You can write a gulpfile using a language that requires transpilation, like TypeScript or Babel, by changing the extension on your gulpfile.js to indicate the language and install the matching transpiler module.
For TypeScript, rename to gulpfile.ts and install the ts-node module.
For Babel, rename to gulpfile.babel.js and install the #babel/register module.
So the simpler way to add TypeScript support in Gulp:
Install ts-node, typescript, and #types/gulp:
$ npm i -D ts-node typescript #types/gulp
If you have a tsconfig.json file set ts-node.compilerOptions.module to "commonjs"
{
// these options are overrides used only by ts-node
"ts-node": {
"compilerOptions": {
"module": "commonjs"
}
}
}
(You don't need a tsconfig.json file, this is just for if you have one in your project already)
Create gulpfile.ts with the following demo code:
import gulp from 'gulp'; // or import * as gulp from 'gulp'
gulp.task('default', () => console.log('default'));
(or rename your existing Gulpfile.js to gulpfile.ts)
Start the build:
$ npx gulp
The output should look similar to this:
$ gulp
[21:55:03] Requiring external module ts-node/register
[21:55:03] Using gulpfile ~/src/tmp/typescript-tmp/gulpfile.ts
[21:55:03] Starting 'default'...
default
[21:55:03] Finished 'default' after 122 μs
In case anyone else runs into this, #tony19's answer above will only work for some projects ;-)
import * as gulp from 'gulp'; won't always work (it depends on your tsconfig.json settings- specifically allowSyntheticDefaultImports), the "safer" thing to use is import gulp from 'gulp'; which should work regardless of the allowSyntheticDefaultImports value.
Set up a gulp.js file in the root of your project with nothing but the following line.
eval(require('typescript').transpile(require('fs').readFileSync("./gulp.ts").toString()));
Then create another actual gulp file written in typescript in a file gulp.ts. What will happen is that the gulp.js file will be loaded but will bootstrap the process by compiling your `gulp.ts' file and passing the transpiled results instead.
This allows us to not have to precompile the gulp.ts file before using it. Instead you can just type gulp test and it will be executed from your tyepscript file without any extra calls.
Make sure to run the following first:
npm install typescript --save-dev
npm install fs --save-dev

UglifyJS - convert all .js in a folder

I was wondering if anyone could help, I'm attempting to finish off my build process which currently transpiles es6 > es5 using babel, After that has completed I want to use uglifyJS to recursively minify all my .js files using just NPM scripts (no grunt or gulp please).
What I desire;
Convert all .js in folder to es5
Minify all .js files in a given folder using uglify
Create source maps
Copy out to a new folder
My current setup;
Converts all .js to es5
Minify all es5 .js files (However no sourcemaps are created, also the es5 js files are replaced as theres no support to move to another folder)
I've tried: https://www.npmjs.com/package/recursive-uglifyjs and https://www.npmjs.com/package/uglifyjs-folder but these both seem unable to perform the build steps I need
Here is my package.json scripts section
"babel": "babel js_uncompiled --out-dir js_uncompiled/es5 --source-maps && npm run npm:uglify",
"build": "npm run babel",
"uglify": "recursive-uglifyjs js_uncompiled/es5"
You can find a link to my full package.json here : http://pastebin.com/4UHZ1SGM
Thanks
EDITED: included info from comments
So, now uglifyjs-folder has the option of passing a config file so you can run all uglify's commands, but on a whole folder (and you can transpile to ES5 using harmony - as stated in comments).
Note this is better than doing so manually with cat or other shell commands, since uglifyjs-folder can generate a single output file (concatenated) and is simpler to use.
Run uglifyjs-folder "%CD%" --config-file "uglify.config.json" --output "folder" -e where the config file (in the root folder of project) contains for example (not all options needed):
{
"compress": true,
"mangle": true,
"sourceMap": {
"base": "input/path/",
"content": "input/sourcemap",
"filename": "{file}.min.js",
"includeSources": true,
"root": "original/source/path",
"url": "source/path"
}
}
Obs.: currently there is one open issue by myself because source-mapping is resulting in error. Once the issue is solved I will update my answer here.
UPDATE: ok, issue solved, version 1.5 released! Code above updated

Copy .js and compile .coffee during Makefile task

I have a node project with:
.coffeescript source in src
compiled coffeescript output to lib
shell scripts in bin
How can I adjust my Makefile, shown below, to also copy .js files in src to the lib directory?
BIN = ./node_modules/.bin
SRC = $(wildcard src/*.coffee)
LIB = $(SRC:src/%.coffee=lib/%.js)
init:
npm install
clean:
#rm -r -f $(LIB)
build: $(LIB)
dist: clean init build
lib/%.js: src/%.coffee
$(call coffeetime)
define coffeetime
#mkdir -p $(#D)
$(BIN)/coffee -bcp $< > $#
endef
Also, if you have any other suggestions to improve the Makefile, please share.
Something like this might work.
Add SRCJS = $(wildcard src/*.js)
Change LIB = $(SRC:src/%.coffee=lib/%.js) to LIB = $(SRC:src/%.coffee=lib/%.js) $(SRCJS:src/%=lib/%).
Add:
lib/%.js: src/%.js
#cp $< $#
If it doesn't work (for some reason) then you may need to use a static pattern rule but I think something like the above should work.
I would suggest you to use Grunt instead.
There is a few neat task that handle Coffeescript compiling very well. Like: https://github.com/gruntjs/grunt-contrib-coffee
Also, depending on your needs, Node.js can cope with Coffeescript directly if needed.

Working project structure that uses grunt.js to combine JavaScript files using RequireJS?

I have some projects that use RequireJS to load individual JavaScript modules in the browser, but I haven't optimized them yet. In both development and production, the app makes a separate request for each JavaScript file, and now I would like to fix that using Grunt.
I have tried to put together a simple project structure to no avail, so I'm wondering if someone can provide a working example for me. My goals are the following:
In development mode, everything works in the browser by issuing a separate request for each required module. No grunt tasks or concatenation are required in development mode.
When I'm ready, I can run a grunt task to optimize (combine) all of the JavaScript files using r.js and test that out locally. Once I'm convinced the optimized application runs correctly, I can deploy it.
Here's a sample structure for the sake of this conversation:
grunt-requirejs-example/
grunt.js
main.js (application entry point)
index.html (references main.js)
lib/ (stuff that main.js depends on)
a.js
b.js
requirejs/
require.js
text.js
build/ (optimized app goes here)
node_modules/ (necessary grunt tasks live here)
Specifically, I'm looking for a working project structure that I can start from. My main questions are:
If this project structure is flawed, what do you recommend?
What exactly needs to be in my grunt.js file, especially to get the r.js optimizer working?
If all of this isn't worth the work and there's a way to use the grunt watch task to automatically build everything in development mode every time I save a file, then I'm all ears. I want to avoid anything that slows down the loop from making a change to seeing it in the browser.
I use the grunt-contrib-requirejs task to build project based on require.js. Install it inside your project directory with:
npm install grunt-contrib-requirejs --save-dev
BTW: --save-dev will add the package to your development dependencies in your package.json. If you're not using a package.json in your project, ignore it.
Load the task in your grunt file with:
grunt.loadNpmTasks('grunt-contrib-requirejs');
And add the configuration to your grunt.initConfig
requirejs: {
production: {
options: {
baseUrl: "path/to/base",
mainConfigFile: "path/to/config.js",
out: "path/to/optimized.js"
}
}
}
Now you're able to build your require.js stuff into a single file that will be minimized with uglifyjs by running grunt requirejs
You can bundle a set of different tasks into some sort of main task, by adding this to your grunt file
grunt.registerTask('default', ['lint', 'requirejs']);
With this, you can simply type grunt and grunt will automatically run the default task with the two 'subtasks': lint and requirejs.
If you need a special production task: define it like the above
grunt.registerTask('production', ['lint', 'requirejs', 'less', 'copy']);
and run it with
grunt production
If you need different behaviors for 'production' and 'development' inside i.e. the requirejs task, you can use so called targets. In the configuration example above it's already defined as production. You can add another target if you need (BTW, you can define a global config for all targets by adding a options object on the same level)
requirejs: {
// global config
options: {
baseUrl: "path/to/base",
mainConfigFile: "path/to/config.js"
},
production: {
// overwrites the default config above
options: {
out: "path/to/production.js"
}
},
development: {
// overwrites the default config above
options: {
out: "path/to/development.js",
optimize: none // no minification
}
}
}
Now you can run them both at the same time with grunt requirejs or individually with grunt requirejs:production, or you define them in the different tasks with:
grunt.registerTask('production', ['lint', 'requirejs:production']);
grunt.registerTask('development', ['lint', 'requirejs:development']);
Now to answer your questions:
I would definitely use a subfolder in your project. In my case I use a 'src' folder for development that is build into a 'htdocs' folder for production. The project layout I prefere is:
project/
src/
js/
libs/
jquery.js
...
appname/
a.js
b.js
...
main.js // require.js starter
index.html
...
build/
... //some tmp folder for the build process
htdocs/
... // production build
node_modules/
...
.gitignore
grunt.js
package.json
see above
You can do so, but I wouldn't recommend to add requirejs to the watch task, it's a resource hungry task and it will slow down your machine noticeable.
Last but not least: Be very cautious when playing around with r.js. Especially when you want to optimize the whole project with r.js by adding a modules directive to your config. R.js will delete the output directory without asking. If it happens that it is accidentally configured to be your system root, r.js will erase your HDD. Be warned, I erased my whole htdocs folder permanently some time ago while setting up my grunt task... Always add keepBuildDir:true to your options when playing around with the r.js config.

Categories