node app with coffeescript and gulp - javascript

I'm pretty new to node, but I'm trying to dive in by taking a framework that's already built (skeleton) and converting it to coffeescript.
So this has a config folder, with config.js, passport.js, and utils.js files... also, obviously, in the root, app.js. He's using gulp, so there's a gulpfile.js. I wanted to convert these files to coffeescript, and not just the user js files. Is that bad practice? I've added gulp-coffee as a devDependency, and coffee-script as a dependency.
Upon rebuilding the aforementioned files, and renaming them...
[12:23:40] 'coffee' errored after 61 μs
[12:23:40] Error: Invalid glob argument
at Gulp.src (/Users/brett/Dropbox/Apps/mean_projects/skeleton/node_modules/gulp/node_modules/vinyl-fs/lib/src/index.js:17:11)
... and further down
[gulp] [nodemon] starting `coffee --debug app.coffee`
/Users/brett/Dropbox/Apps/mean_projects/skeleton/config/config.coffee: line 1, col 1, Expected an assignment or function call and instead saw an expression.
/Users/brett/Dropbox/Apps/mean_projects/skeleton/config/config.coffee: line 1, col 13, Missing semicolon.
/Users/brett/Dropbox/Apps/mean_projects/skeleton/config/config.coffee: line 3, col 1, Expected an identifier and instead saw '#'.
That shows config.coffee, and there are blocks of errors for each of the files that I converted from js to coffee (app, app_cluster, gulpfile, utils, passport, etc).
Any help on the topic would be good... I've been reading quite a few articles (some that hate coffeescript) but nothing that really shows how to handle this.

If you use gulp 3.7+, then gulpfile.coffee is supported out of the box. No need to do any extra setup.
If you have to use an earlier you can bootstrap coffeescript, by just putting this in it:
// Note the new way of requesting CoffeeScript since 1.7.x
require('coffee-script/register');
// This bootstraps your Gulp's main file
require('./Gulpfile.coffee');
Then you can put you setup in gulpfile.coffee.
Is that what you meant?

Related

webpack require with dynamic path

My colleague put something like this in our code:
const information = require('../relative/path/' + tag + '.json');
The funny thing is that it works, and I don't really see how.
I have created this minimal project:
$ head *.json main.js
==> 1.json <==
["message #1"]
==> 2.json <==
["message two"]
==> 3.json <==
["message III"]
==> package.json <==
{
"dependencies": {
"webpack": "^5.38.1"
"webpack-cli": "^4.7.2"
}
}
==> package-lock.json <==
...
==> main.js <==
const arg = process.argv[2] ? process.argv[2] : 1;
console.log(require(`./${arg}.json`)[0]);
when I run the original program, I get this:
$ node main.js 1
message #1
$ node main.js 2
message two
$ node main.js 3
message III
so now I compile with webpack
$ node_modules/.bin/webpack ./main.js
and it creates a dist directory with a single file it in, and that new bundled program works too:
$ node dist/main.js 1
message #1
$ node dist/main.js 2
message two
$ node dist/main.js 3
message III
and when I look inside the bundle, all the info is bundled:
When I remove the require from the program, and just print the arg, the bundled program is a single line.
So how does it do it?
somehow calculate every possible file?
just include everything from the current directory down?
Funny thing is in my simple example, package.json ended up in there too, but in the real one that gave me the idea, it didn't.
Does anybody know how this works?
I mean the simple practical answer for me is, never put variables in require... but I am still curious.
PS the real one is a web project. just used node and args for the example
Webpack always bundles all require'd files into the final output file (by default called bundle.js). You cannot require anything that was not bundled.
If you require something that is not a constant, as you pointed out, it might lead to some trouble. That is why eslint has a no-dynamic-require rule for that. But if you know what you are doing, everything is just fine.
Webpack uses some heuristics to support non-build-time-constant values (i.e. expressions) for require. The exact behavior is documented in webpack's documentation on dependency management.
As explained in that link, your require('../relative/path/' + tag + '.json') will lead webpack to determine:
Directory: ../relative/path
Regular expression: /^.*\.json$/
And will bundle all files matching that criterion.
When your require call is executed, it will provide that file that matches it exactly, or throw an error if that file was not bundled.
Important: This means, of course, that you cannot add files after bundling. You must have files in the right place, before bundling, so they can be found, added and ultimately resolved by webpack.
Also note that often times, you don't need to write your own webpack experiments. Webpack has plenty of official samples. E.g. your case is illustrated exactly by this official webpack sample.

Laravel Elixir 6 getting exception on "gulp watch"

When I try to run gulp watch, I'm getting this error:
stream.js:74
throw er; // Unhandled stream error in pipe.
^
Error: ENOENT: no such file or directory, stat 'XXXX\public\build\css\client-18724fe72d.css'
at Error (native)
I tried to leave the client.scss file empty, and the error disappeared. I found out that the errors sometimes is appearing when I have these lines in my client.scss:
// Pages
#import 'pages/client/auth';
#import 'pages/client/normals';
#import 'pages/client/orders';
I've already checked each one of them, and there's nothing wrong with the syntax or something like that. Even more, when I run gulp, it works without any errors.
This is my gulpfile.js:
const elixir = require('laravel-elixir');
elixir(mix => {
mix
.sass('app.scss')
.sass('client.scss', 'public/css/client.css')
.sass('panel.scss', 'public/css/panel.css')
.copy('resources/assets/fonts', 'public/build/fonts')
.copy('resources/assets/images', 'public/build/images')
.webpack('app.js')
.webpack('panel.js')
.version(['css/app.css', 'css/client.css', 'css/panel.css', 'js/app.js', 'js/panel.js'])
});
This is the file structure:
Is there something that I'm doing wrong here?
As you can see in my gulpfile.js, I copied files/folders to /build folder which is probably a problem on Laravel Elixir 6, and when I think about it now, it's sounds a bad approach too.
So what I did to fix the issue was:
removing these lines from gulpfile.js:
.copy('resources/assets/fonts', 'public/build/fonts')
.copy('resources/assets/images', 'public/build/images')
placing the fonts and images folders into the storage/app/public
running php artisan storage:link (storage:link artisan command)
changing the paths in the assets files to the new directory
running gulp
And it fixed my problem. Now I can do gulp watch again.
Credit to ejdelmonico on laracasts.
Throwing my two cents in here. I had the same issue and it went away as soon as I stopped using the starting / relative path option, and used full relative paths (relative to /resources) instead.
So instead of:
mix.styles([
'vendors/jquery-steps/demo/css/jquery.steps.css',
'vendors/pace/pace-minimal.css',
'vendors/bootstrap/dist/css/bootstrap.min.css',
'../node_modules/sweetalert2/dist/sweetalert2.min.css',
], 'public/css/vendors.css', 'public');
This worked, and gulp watch ran again:
mix.styles([
'../../../public/vendors/jquery-steps/demo/css/jquery.steps.css',
'../../../public/vendors/pace/pace-minimal.css',
'../../../public/vendors/bootstrap/dist/css/bootstrap.min.css',
'../../../node_modules/sweetalert2/dist/sweetalert2.min.css',
], 'public/css/vendors.css');
It's not pretty, but it works.

Visual Studio 2015 compiles ALL typescript files when SINGLE file is changed

I am using Visual Studio 2015 with Typescript 1.5.4 and Resharper 9
This is the buggy scenario:
I have about 180 typescript files
I change single .ts file
VS shows message "Generation of XXX.ts file complete. Remaining files still compiling"
after that ALL my .ts files are compiled to .js
2 things were changed in those .js files: formatting is slightly different and reference for .js.map was removed
When I build the whole project, then the .js files are generated again but with original formatting and with link to .js.map present
This is annoying because it generates too much noise in Git
and it prevents me from debugging typescript files directly in browser. (because of that missing .js.map file)
The desired behaviour is of course that the only changed .ts file should be compiled on save. How to do it?
It seems that R# has nothing to do with this, because it continues to happen with R# disabled.
My current project settings:
-------------UPDATE-------------
I've tried to update to Typescript version 1.6.
The PATH variable pointed to C:\Program Files (x86)\Microsoft SDKs\TypeScript\1.4\ so I've updated that to point to 1.6
So when I now type tsc -v it says message TS6029: Version 1.6.2
But because of historical reasons (the project I work on is about 2 years old) I have to use version 1.4 inside VisualStudio. So in the .csproj is <TypeScriptToolsVersion>1.4</TypeScriptToolsVersion>
After this change the compile on safe stopped working completely.
Now I have to rebuild the whole solution :(
It seems that Visual Studio does not support watch mode properly (i.e. incremental compilation):
Just to be clear, --watch does work on Windows if you're using
node.js/io.js, but the tsc.exe program distributed with VS does not
support it; you still have Compile on Save for similar functionality
anyhow.
https://github.com/Microsoft/TypeScript/issues/2375#issuecomment-100812347
I'm not sure why this was closed. Supporting --watch for our tsc.exe
host would both be possible and desirable. Right now the limiting
factor is that our tsc.exe host is a bit of ugly C++, that uses some
ancient COM interfaces for Chakra that we haven't spent much effort
on. Our options are: [...]
https://github.com/Microsoft/TypeScript/issues/2375#issuecomment-100949019
As a workaround, could you run
tsc --watch
in the folder where tsconfig.json is located?
Edit: https://github.com/Microsoft/TypeScript/issues/5638 - Visual Studio 2015 compiles ALL typescript files when SINGLE file is changed
Starting with VS 2015 RTM, Compile-on-Save, every time you save a file
we need to generate all files in the project to ensure consistent
output. We have got numerous issues related to inconsistent output
when saving files in different orders. Building all files is the only
way we can guarantee correct and consistent output given all the
language constructs and how they interact across files (e.g.
namespaces/internal modules can be augmented, and that affects the
shape of emitted code, also const enms are in lined as constants,
etc..).
Try "ECMAScript 5" instead of "ECMAScript 3" in "ECMAScript version
I had a similar issue, but since we were handling TS compilation on our own, I wanted to avoid auto-compilation at all...
The fix was to force the TypeScriptCompileOnSaveEnabled flag to false inside the project:
<PropertyGroup>
<TypeScriptCompileOnSaveEnabled>false</TypeScriptCompileOnSaveEnabled>
</PropertyGroup>
in my case this effectively stopped VS2015 from automatically compiling the .ts files on save, without VS getting into the way every time and messing up outputs...
Another work around: You could use Gulp to generate your compiled js files and maps. With Gulp you can also create a watch task to compile at a save of a ts file. You can even create clean tasks to clean up the project.
Example of a build task:
var tsProject = ts.createProject(paths.typescriptRoot + 'tsConfig.json'); // use tsconfig.json
gulp.task("tsbuild", function () {
var tsResult = tsProject.src()
.pipe(sourcemaps.init()) // needed to create sourcemaps
.pipe(ts(tsProject)); // use tsconfig.json
return tsResult.js
.pipe(concat(paths.concatTsFileName)) // concat all output files into a sings js files
.pipe(sourcemaps.write()) // write the sourcemap to be able to debug the ts files
.pipe(gulp.dest(paths.typescriptOut)); // output the result on specific path
});
Example of a cleanup task :
gulp.task("clean:tsout", function (cb) {
rimraf(paths.typescriptOut + paths.concatTsFileName, cb); // rimraf is used to delete a folder
});
gulp.task("clean:scriptjs",
function () {
return gulp.src(paths.typescriptJs, { read: false }) // to clean up multiple files we need to use gulp-rimraf
.pipe(gulpRimraf());
});
Example of a Watch task:
gulp.task("watch:tsbuild", ['tsbuild'], function () {
gulp.watch(paths.typescriptRoot + '**/*.ts', ['tbbuild']);
});

WIKI: How to use Lime (how to use closure-compiler with 3rd party (closure) libraries)

The following post inspired me to have a look at limeJS, as a side project I'm working on and off an a Yatzee game (mostly off) and thought that might be a nice library to use.
As a beginner in google-closure I had some difficulties running uncompiled code and getting code compiled, mostly due to not knowing what the options and commands are and because of dependencies.
For other beginners with google-closuse I have written this tutorial.
Note that jQuery can be used by your closure compiled code but you need the jQuery externs file. You can't compile jQuery into your code, closure library has a dressed down dojo that can be found in third_party. When using that you can compile your code to one file.
What you need:
Python
Git client
Closure compiler for compiling code (minifying and merging all files into one)
Closure library like jQuery and jQuery ui but can be compiled along with your code
Python (I use 2.7)
LimeJS As a 3rd party library (use git client to get it, the url:https://github.com/digitalfruit/limejs.git)
JAVA JRE
Directory structure
I'm using Windows and have my projects in D:\projects, if you have your projects somewhere else you have to replace D:\projects references to your own.
In D:\projects I make a directory called libraries in that directory I copy the goog and third_party directories from closure library (goog is under the closure directory) since you'll use them for many projects I keep it at projects root, you can include a copy of it in every project you create but in this case I'll share the library among all projects.
Now I copy the contents of the src directory from limeJS ([lime clone dir]\lime\src) to D:\projects\libraries\lime (the one containing the sub directories called animation, audio ...).
Next I'll use an existing project from the limeJS library, copy the [lime clone dir]\lime\demos\roundball to D:\projects\roundball
At this time your directory structure should look like this:
D:
projects
libraries
goog
lime
animation
audio
css
...
third_party
closure
...
roundball
assets
... other roundball stuff
cacldeps.py
When you open D:\projects\roundball\rb.html and check out the console (press F12 in Chrome or in FireFox preferably having firebug plugin installed) you'll see an error: "ReferenceError: goog is not defined"
Open up D:\projects\roundball\rb.html and change:
<script type="text/javascript" src="../../../closure/closure/goog/base.js"></script>
to
<script type="text/javascript" src="../libraries/goog/base.js"></script>
Now when you open up rb.html again you get a different error: "goog.require could not find: lime.Director"
This is because closure uses deps.js to find dependencies and since lime is not in there it can't find it. Lucky for us there is a tool called calcdeps.py in the bin directory of the closure library that can create this file for us. It'll look in your code and and use goog.require to figure out what other files are needed. If your file structure is good than this tool will find it.
It will expect that Director is in a file called director.js in a directory called lime (and it is). That js file should have a goog.provide statement providing lime.Director.
You can add directories for calcdeps.py to look in with the --path parameter.
In D:\projects\roundball I'll create a makedeps.bat with the following content:
set calc="D:\software\closure compiler\library\closure\bin\calcdeps.py"
c:\Python27\python.exe %calc% ^
--path D:\projects\roundball\ ^
--path D:\projects\libraries\ ^
--input D:\projects\roundball\rb.js ^
--output_mode deps ^
--output_file D:\projects\libraries\goog\deps.js
pause
Uncompiled code uses /goog/deps.js to load dependencies. caclcdeps.py will check your code starting with rb.js (as this is the starting point of the code) and add entries to deps.js according to what your project uses.
Once again, cacldeps.py can be found in the bin directory of closure library.
Note that when you have another project; let's say D:\projects\project2 then you have to create a makedeps.bat in that project directory that re creates the deps.js for you before you can run the uncompiled code. This because multiple projects share one google closure library so when you switch projects make sure you'll build the deps.js first before running your uncompiled code.
Resolving missing dependency
Opening the rt.html we still get an error but a different one: Error: "Undefined nameToPath for lime.css"
Looking in goog/deps.js we can find that lime.css is needed by lime but doesn't have an entry in deps.js. Why is this? Looking in D:\projects\libraries\lime there is no css directory or css.js file. But in the directory where you cloned the git lime project there is a directory called css.
Copy the css directory to D:\projects\libraries\lime and run makedeps.bat again, now when you open rt.html it will run.
The whole thing is uncompiled and you can set breakpoints to step into 3rd party code.
Compile your code
In production you would want to compile the code to one file. To compile the code I created a compile.bat in D:\projects\roundball with the following content:
set calc="D:\software\closure compiler\library\closure\bin\calcdeps.py"
c:\Python27\python.exe %calc% ^
--path D:\projects\roundball\ ^
--path D:\projects\libraries\ ^
--input D:\projects\roundball\rb.js ^
--compiler_jar "D:\software\closure compiler\compiler.jar" ^
--output_mode compiled ^
--compiler_flags="--compilation_level=ADVANCED_OPTIMIZATIONS" ^
--compiler_flags="--formatting=PRETTY_PRINT" ^
--output_file D:\projects\roundball\compiled\roundball.js
pause
;Need this flag for production compile:
;--compiler_flags="--define goog.DEBUG=false" ^
;Remove the following flag from production compile:
;--compiler_flags="--formatting=PRETTY_PRINT" ^
;lime libraries is giving me errors with stricter compilation
; so had to remove this flag (have to fix the errors or no type checking for your code)
;--compiler_flags="--warning_level=VERBOSE" ^
The file compiler.jar can be found where you downloaded (and extracted) closure compiler
Now when you run the compile.bat and open D:\projects\roundball\compiled\roundball.html you'll see in the developer tools of your browser that only roundball.js is loaded.
The answer is in the question because it's a howto article that could help someone (like me in the future when I forgot how to do it).

Node.js/ v8: How to make my own snapshot to accelerate startup

I have a node.js (v0.6.12) application that starts by evaluating a Javascript file, startup.js. It takes a long time to evaluate startup.js, and I'd like to 'bake it in' to a custom build of Node if possible.
The v8 source directory distributed with Node, node/deps/v8/src, contains a SconScript that can almost be used to do this. On line 302, we have
LIBRARY_FILES = '''
runtime.js
v8natives.js
array.js
string.js
uri.js
math.js
messages.js
apinatives.js
date.js
regexp.js
json.js
liveedit-debugger.js
mirror-debugger.js
debug-debugger.js
'''.split()
Those javascript files are present in the same directory. Something in the build process apparently evaluates them, takes a snapshot of state, and saves it as a byte string in node/out/Release/obj/release/snapshot.cc (on Mac OS). This file seems to be baked into Node.
Some customization of the startup snapshot is possible by altering the SconScript. For example, I can change the definition of the builtin Date.toString by altering date.js. I can even add new global variables by adding startup.js to the list of library files, with contents global.test = 1.
However, I can't put just any javascript code in startup.js. If it contains Date.toString = 1;, an error results even though the code is valid at the node repl:
Build failed: -> task failed (err #2):
{task: libv8.a SConstruct -> libv8.a}
make: *** [program] Error 1
And it obviously can't make use of code that depends on libraries Node adds to v8. global.underscore = require('underscore'); causes the same error.
I'd ideally like a tool, customSnapshot, where customSnapshot startup.js evaluates startup.js with Node and then dumps a snapshot to a file, snapshot.cc, which I can put into the Node source directory. I can then build node and tell it not to rebuild the snapshot.
I just added an option to the mksnapshot command (which runs while you are building V8). The new --extra-file=filename.js flag lets you specify a file that is to be loaded and run in the process and then put in the snapshot. It's on the trunk version of V8, not the 3.11 branch that is being used for node 0.8 so you will have to run node 0.8 with V8 version 3.11. As far as I know at the moment that works, but you will be somewhat on your own.
Please file bugs if you try this and it doesn't work for you.

Categories

Resources