Clientside Javascript in Typescript Express projects - node.js

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.

Related

How can I use NPM modules with Django inside an app?

I have a Django project with 2 apps. I want to use the Notion API in one of the apps, so I have to install it's NPM module. However, I have never use NPM nor a bundler (I understand I have to use one for the import statement).
I have no idea on how to do it. Where should I install the module? Should I install Webpack or something similar? How can I integrate both of this technologies with Django?
Can someone please explain this to me, or reffer to an article/video explaining?
I have been trying for hours now and I can't find anything detailed.
I have checked the following links:
Django how to use npm modules with static/ templates
https://gist.github.com/brizandrew/685a588fbefbd64cd95ed9ec4db84848
https://www.saaspegasus.com/guides/modern-javascript-for-django-developers/integrating-javascript-pipeline/
https://www.saaspegasus.com/guides/modern-javascript-for-django-developers/integrating-javascript-pipeline/
https://www.techiediaries.com/django-webpack-react/
https://owais.lone.pw/blog/webpack-plus-reactjs-and-django/
https://pythonrepo.com/repo/owais-django-webpack-loader-python-developing-restful-apis
And a lot more.
They either don't have what I need (they are for react), or I can just not understand them. I know there are probably a lot of articles on this, but either I just can't find them, or they are too complicated for me (sorry I'm dumb).
If anyone can help me, it would make my day.
Thanks!
P.S. I am using Typescript, but I can use vanilla JS if necessary.
You have two things to do in order to get your app working the way you want.
Install, configure, and run a module bundler
Use collectstatic
Module bundler:
You have a few choices, but most use webpack because it is the most popular. I prefer rollup but it is all up to preference.
rollup quickstart: https://rollupjs.org/guide/en/#quick-start
webpack: https://webpack.js.org/concepts/
Since you are using Typescript, see the plugins for bundling Typescript
https://webpack.js.org/guides/typescript/
https://github.com/rollup/rollup-plugin-typescript
After you bundle, you should have a main.js file or equivalent. Make sure that main.js is in its own folder. Bundlers will typically do this for you.
Add that directory to your STATICFILES_DIRS in settings.py.
Note that you will need to set a STATIC_ROOT for this to work. This will be a folder that you will store your collected static files at.
Run python manage.py collectstatic
Sidenote: if you are using python manage.py runserver to start your application, you don't need to run collectstatic
For those looking for a -workaround solution- this should be great
I found this website that provides you with the bundles to imported in your static files (.html)
So, for my case I needed to download Chart.js latest version's bundle and I found it available here
https://cdnjs.com/libraries/Chart.js
and add it to your html like so:
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.8.0/chart.min.js" integrity="sha512-sW/w8s4RWTdFFSduOTGtk4isV1+190E/GghVffMA9XczdJ2MDzSzLEubKAs5h0wzgSJOQTRYyaz73L3d6RtJSg==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>

Compile a typescript node js app including dependencies

I have created a Node.js app using typescript and trying to compile it. Currently, the build only contains the source files in the src folder. But I also want to include the dependencies like express, body-parser, etc from node_modules in the final build. This is similar to how webpack compiles all the files together creating bundles.
How can I do this using the typescript compiler only? Or it can be done using webpack only?
Please help.
Typescript compiler only compiles typescript to javascript. You have to manage yourself the build as you want.
I would use a post script to organize your program. Here is a example of pre and post script using npm run build Pre and post script gist

How to working with css framework in npm

I tryed to use css frameworks lots of times. But i cant found any guide what to do. Just some post from other developers. Can you help me with the guide, how to import and use css framework in my expressjs project.
For instance, i started new project with express generator:
express --view=pug --css=sass
next, i installed materialize
npm install materialize-css
What i must to do next??? How to connect js and sass files with my project? How to compile all, if i tryed to do just a website? Where i can find good guides about such things, if i will have more questions?? Thanks!
npm was originally to get Node Module, but with the essort of the Javascript language (and the advent of browserify, webpack,etc), it has a bit grown up.
In fact, you can even download Bootstrap on npm, that is not a server side framework. Browserify permits you to use AMD/RequireJS/CommonJS on client side so node modules can be used on client side. Same goes for Webpack module bundler.
If you npm install bootstrap (if you don't use grunt or gulp file to move to a dist folder), your bootstrap will be located in some location like below.
"./node_modules/bootstrap/bootstrap.min.css"
You need to include this in your .html file.
For sass if you use grunt then you will be using this plugin grunt-sass to convert sass to css and add the destination file to the .html file. Similarly goes for gulp.

Use npm package on client side

is there a way I can use an npm package on the client side? For example, I want to use the dateformat(https://www.npmjs.com/package/dateformat) package in my client side javascript file
If you want to use npm on the client you may consider using browserify which is designed for that purpose. The node module system is not compatible with browsers so browserify transpiles the javascript into something that will work. Hence the name : browserify.
I found it wasn't enough to use Browserify. There were still issues with the client-side not finding the variables/functions from the library.
Here are the steps that worked for me:
Install Browserify:
npm install -g browserify
Install a library from npm (I'll use leader-line as an example):
npm i leader-line
You will now have all the npm files needed inside the node_modules directory:
Now we can run the usual Browserify command to bundle the JS file from the npm package:
browserify node_modules/leader-line/leader-line.min.js -o bundle.js
This will produce a bundle.js file outside of node_modules:
This is the file we can bring into the front-end, as we would with a usual JS library.
So, assuming I added my bundle.js file to a libs folder, and renamed bundle.js to leaderline.js, I can simply add the usual line in the header of my index.html file:
<script src="libs/leaderline.js" type="module"></script>
Notice the addition of type="module" to the script tag.
However, this is STILL not enough. The final step is to open the JS file for the library (in my case leaderline.js) and find the main function that needs to be exported (usually somewhere near the top):
var LeaderLine=function(){"use strict";var te,g,y,S,_,o,t,h,f,p,a,i,l,v="leader-line"
I need LeaderLine to be available inside my scripts. To make this possible, we simply remove var and add window. in front of the function name, like this:
window.LeaderLine=function(){"use strict";var te,g,y,S,_,o,t,h,f,p,a,i,l,v="leader-line"
Now I can use the library client-side without any problems:
HTML:
<div id="start">start</div>
<div id="end">end</div>
JS
new LeaderLine(
document.getElementById('start'),
document.getElementById('end')
);
Some will argue that exposing the function to the window is too "global" for best practices. But the other option is to use module bundlers, which handle the exposing of packages, and this is overkill for many applications, especially if you're trying to whip together a quick front-end to try something out.
I find it odd that so many now publish packages in npm, that are obviously intended for the front-end (e.g. obviously nobody would use leaderline.js in back-end node, yet this is where the package was published, with no available CDN).
Given how tortuous it is to expose front-end functionality from an npm package, one can argue that today's JS ecosystem is a mess.
Most of the packages on NPM are designed for server side and won't work on the client side because of security reasons. You could use NW.js, but the user would have to install your software on there computer.
"NW.js (previously known as node-webkit) lets you call all Node.js modules directly from DOM and enables a new way of writing applications with all Web technologies."
http://nwjs.io/

Front-end dependencies via npm: how does it work?

I've installed backbone via npm, it is placed in node_modules folder (not in web root) how can i include it in my index.html file?
It's possible to write front-end code entirely based on CommonJS (i.e. Node-style) modules.
If you install front-end dependencies through npm you can use a package bundling tool like Browserify to bundle all dependencies into one file. This way you can use the browser-dependent packages in the same way you use server-side packages: with Node's require function. You just require a module (either in node_modules dir or a regular file) and work with it.
Base use of browserify is really simple: Just do browserify clientcode.js > webroot/clientbundle.js, where webroot is your web root. Then include clientbundle.js in your html file.
clientcode.js should be the client's "main" script, comparable to the "app.js" (or similar) of an Express app or so. It can be as big as you want, but you could just as well use it only as bootstrap code to run functions defined in other CommonJS modules.
Note that you can easily mix browserified dependencies with regular dependencies. Any scripts that you include beforehand (say a non-browserified jquery) will just become a global, and browserify does not prevent you from accessing globals.
Beware though: Some packages distributed via npm based on client-side libraries do not conform (entirely) to CommonJS spec. Some may not export anything, some may (unexpectedly) create globals, etc.
See also Backbone app with CommonJS and Browserify .
Some alternatives to browserify:
https://github.com/michaelficarra/commonjs-everywhere
https://github.com/medikoo/modules-webmake
https://github.com/webpack/webpack
I haven't tried them though.
While the idea of using npm for both backend and frontend may sound tempting–it certainly did to me–try Bower or Ender.js instead for frontend dependencies. I personally prefer bower, because I can more easily include it into my requireJS module structure. It will keep you from foaming at the mouth with frustration.
Front-end dependency I would recommend using Bower. There are many components available for you to use and they are really easy to setup.

Resources