I'm using coffeescript while writing a node js app and use cake watch to compile my js files real time.
That's great to be able to do that - but where should I stick those js files? Right now, I'm saving them right next to their respective coffeescript files, but that just feels awkward...
The convention I've gotten comfortable with is to put CoffeeScript files in a src directory and have "compiled" JavaScript output to a lib directory. Like so:
package.json
lib/mymodule.js
src/mymodule.coffee
If you publish the module to the npm registry, you can just include the resulting lib directory, which is conventionally where projects written in JavaScript keep there .js files. This keeps everything consistent.
Related
I always wondered how I can properly add the clientsided javascript in my express project. I use Typescript and I would also like to take advantage of the Typescript typings (for jquery for instance) when writing my clientside javascripts.
My project structure looks like this:
root
dist
src
helpers
models
registration
router.ts
form.pug
profile
router.ts
profile.pug
wwwroot
css
js
images
What I have done until today:
I created all clientsided javascript files in wwwroot/js (e.g. jquery.min.js, registration-form.js) and I loaded them into the header of the appropriate pages.
Disadvantages:
I had to write ES5 javascript which is compatible with the browsers we would like to support
I couldn't put the javascript files where they logically belong to (e. g. I'd rather put my registration-form.js into src/registration/ instead of the wwwroot)
No Typescript possible :(. No typescript typings, no transpiling to ES5 etc.
In some tutorials I saw they would simply run npm install --save jquery and import it in their clientsided files. So I feel like I must have missing some pretty important stuff, but I couldn't find any tutorials about it.
My question:
What is the "right way / best practice" to write clientsided javascript in Typescript / Express applications (which should also elliminate also the mentioned disadvantages)?
Using TypeScript on the client side is not much different from the server side.
Here is what you can do:
Create client folder for client-side typescript sources
Put tsconfig.json into client folder and configure it to produce "es5" code (target: es5)
Install jquery types (npm install --save-dev #types/jquery)
That's it, now you can write your client side code in TypeScript.
You can compile server-side code with tsc -p ./src (having server-side tsconfig.json under src) and compile client-side code with tsc -p ./client.
I made a simple example of such app, check it here. I put the simple script to build everything into package.json, so you can run npm run-script complie to get both server and client code complied into /dist folder. Then run it with npm start.
Further steps:
Automate your flow: you should be able to start your app locally and then just edit source TypeScript files and the app should be reloaded automatically. This can be done with webpack / gulp / grunt or custom shell script that can be triggered once any of your source file has been changed and saved.
If you find yourself writing good amount of client-side code, check also angular (https://angular.io/docs). It uses TypeScript as preferred language for client-side development and you'll be able to build much more powerful client-side app using it. You may choose another library as well (react, vue.js, etc), see the examples on the TypeScript site.
I have 2 files in a folder called js. I am using webpack.
js/app.js and js/login.es6.
I'm trying to include the login from my app.js:
require('login.es6') fails
require('./login.es6') works.
Any idea why?
When you write require('login.es6') node will look for a module named login.es6 in your node_modules.
When you write require('./login.es6') node understands that ./login.es6 is a relative path and will load your js/login.es6.js file.
This is needed to distinguish between modules and local files. There may be a npm module called login.es6; this way you can reference both the module and your local file in your project.
The node.js docs on require are pretty nice and gives a good overview of how modules are prioritized when loaded.
The gist is, if you don't start the string with ./, require will first look for a core module, then recursively look in the node_modules directory/-ies. So it's normal to start require calls to local files with ./.
Ive just published my first package (a react component) to npm but im having some trouble understanding the difference between what the lib directory is compared to the dist.
Currently I generate both lib and dist however my package "main" points to the dist unminified js file which has been built using webpack and output as UMD. The lib folder is built using babel taking the src and outputting to lib.
The dist folder contains both [unminified/minified].js files as well as [unminified/minified].css files.
My main confusion is with the lib folder since imports from there currently wouldn't work seeing as I just transform src -> lib meaning the scss references are still there and the scss files aren't transformed either.
I use CSS Modules (css-loader, styles-loader, postcss-loader etc) to generate my CSS files and this is where the confusion is since, wouldn't I also need to use webpack to generate my lib folder seeing as the scss files/import references need to be transformed to css?
Are you meant to have both lib and dist or is the UMD build in dist fulling the same purpose as that of having a lib folder?
If you are supposed to have both how would I achieve this, since I couldnt find any info regarding generating the lib folder when using CSS modules within your js files and still maintaing the same folder structure of that of src (while still generating dist)?
Usually the dist folder is for shipping a UMD that a user can use if they aren't using package management. The lib folder is what package.json main points to, and users that install your package using npm will consume that directly. The only use of the lib as opposed to src is to transform your source using babel and webpack to be more generally compatible, since most build processes don't run babel transforms on packages in node_modules.
As far as handling the style imports, it's probably a good idea to not import scss or css files in your source js that you export. This is because node can't import styles like that by default. If you have an example that demos your component, it makes sense to import the styles there. The common pattern is to publish minified and unminified css in the dist folder, and in your documentation tell the consumer to explicitly import the css file using whatever technique they prefer. I took this approach with redux bug reporter if you need an example. Hope that helps!
In general lib refers to libraries that are included in a package, dist on the other hand are distribution files for your project. As an example you could write a bunch of javascript and include jquery (which is a lib) and then when they're all bundled up you have a single dist file.
Ok think I found out how to do this. There is a babel plugin that allows you to use webpack loaders when running babel (babel-plugin-webpack-loaders). Thus my CSS mapping is inlined within the js file and the mapping hashes used are also the same as that used when building dist. Yay!
With the default version of sails on npm (v.9?) --linker works ok i.e. creates /linker folder. I can copy js, css files to assets/linker/ and they appear in layout.ejs automatically.
I now have sails v0.10 installed both locally and globally. Using Node V0.10.25.
I created a new sails project using:
sails new project_name --linker
but no /linker folder is created.
I had to create /.tmp as it did not exist
I had to create /.tmp/public/linker/ to put /js & /styles
and add them manually into layout.ejs
I renamed Gruntfile.js and my program still works thus Gruntfile does nothing in the program.
Sails v0.10 no longer uses the linker folder--it was just causing confusion. If you have the linker option enabled, then any assets under your assets folder will be copied over to your .tmp/public folder by Grunt when Sails is lifted. The public folder will be created by Grunt as necessary. The grunt-sync task will then keep the folders synced as long as the program is running.
Sails projects are not dependent on Grunt, so renaming the Gruntfile (or removing it completely) won't stop the program from working, but that doesn't mean it's not doing anything when it's there! To see what Grunt is up to, you can lift Sails with sails lift --verbose.
As an add-on to sgress454's answer, the reason a .tmp folder is created is so that files like the ejs and less files can be compiled into formats that your browser will understand. It's similar to the way that when you compile Java, it converts to Java bytecode (just an analogy, definitely not the same process).There doesn't necessarily have to be any .tmp folder when you're not running the server though; this is something Grunt creates and is what the browser reads from. Hope this clarifies things a bit more.
I'm using ExpressJS and the app.js is straight JavaScript. If I wanted to use CoffeeScript, would I have to rewrite app.js or can I just write my additional files with CoffeeScript?
Are you talking about using CoffeeScript on the server side, or serving it as compiled JavaScript to the client? Either way, it's pretty easy.
You can load .coffee files with require, as long as your application has loaded the coffee-script library first. So just start your app with
require 'coffee-script'
(after installing it with npm, of course) and from that point on, any time you write
require 'foo'
from any part of your app, it'll look for both foo.js and foo.coffee. (Obviously the converse is true that a .coffee file can require a .js file; from Node's perspective, the .coffee file is just JavaScript.)
As for serving CoffeeScript as JS to the client from Express, I suggest taking a look at my connect-assets middleware.
As of Coffeescript 1.7.0 you need to
require('coffee-script/register');
vs the mentioned
require('coffee-script');
If you require("coffee-script") from a .js file, you can then subsequently require("some-module") where some-module is written in CoffeeScript and it will 'just work' without a manual compilation step required.
See this question: require()'ing a CoffeeScript file from a JavaScript file or REPL