How to structure NestJS monorepo and build application with relevant assets? - nestjs

Situation
I am building a set of applications based on a NestJS monorepo.
I have severals apps that relies on severals shared libs.
Those apps are similar to one another, but may still differ on some features, so the monorepo totally makes sense.
Some of the libs provides #Controller(), which #Render() views for common features.
 Assomptions
Template files should live in the module.
Since there is a high coupling between the controller and the rendered template,
I believe it makes sense to store the views template files (.hbs, .ejs, whatever) in the libs module providing the #Controller,
Only relevant templates should be shipped in dist/ when I build an app
I have some business/legal/security constraints that force me to avoid the presence of some libs in some apps production environment.
eg. my-secret-algo-lib should not be present in my-public-unsecure-internet-app
So it makes a file structure like this :
monorepo/
apps/
my-first-app/
src/
main.ts <-- nest bootstrap function is here
...
my-second-app/
...
libs/
my-first-lib/
src/
my-first-lib.module.ts
my-first-lib.controller.ts <-- #Render('my-view')
...
views/
my-view.ejs <-- the view
...
Goal
I want to achieve a build that produce the following file structure :
dist/
apps/
my-first-app/
main.js
views/
my-first-lib/
my-view.ejs
Assuming that:
my-first-app imports my-first-lib
Views that may exists in unused libs should not be included in dist/
 Questions
Is this possible with existing tools?
Would this be considered an anti-pattern? if so how should I structure things ?
If the answer to both is "no", should I build something myself or join any existing effort?
Another part of the problem is NestJS application module configuration, but I guess this comes last...

Related

restructuring Nodejs Express Project

I want to restructure Nodejs Express Project that contains v1 and v2 folders inside routes directory.
when restructuring the code to MVC approach, should i have MVC structure for v1 and another MVC structure under v2?
Ideally controllers should be versioned as v1, v2, etc., as they will contain your application logic, which is going to change from time to time, and you'll need to support users using the logic of older version of your application (fallback compatibility).
Models will contain schema for records stored in your database, which should remain consistent across all versions of your controllers. Therefore it should remain outside of your v1, v2, etc. (Like, User will contain same fields regardless of the difference in application logic versions). Changes in models are generally not drastic, as you'll have to define them in a way which doesn't require huge changes later on. In case of a drastic change, you'll have to update the logic across all versions of your controllers accordingly.
Views, can either be versioned or not, depending upon whether you'd like to serve separate views depending upon api version.
Overall, the project structure may look like this
src/
models/
ModelA.js
ModelB.js
...
routes/
v1/
index.js
...
v2/
...
views/
index.ejs
...
server.js
package.json

Path alias with typescript for express static folders?

Context:
I have an express web server which I'm using as a sort of 'template' to create solutions for customers. The needs and use-cases of customers in the industry I work in are all somewhat similar, and therefore most static resources (images, es6 modules etc.) are shared between them. These are all in the root /static/ folder. There are cases where the customers needs necessitate individualized scripts and resources in which case I place them under their respective solution folder, e.g. solutions/solutionA/static/def.js for customer A. In server.js, the express launcher script, I set two static directories through middleware. /static (for shared stuff), and /solutions/ACTIVE SOLUTION/static (for solution specific stuff), where ACTIVE SOLUTION is a constant string specified at the top of the file.
node_modules/
static/
abc.js
solutions/
solutionA/
static/
def.ts
solutionB/
static/
ghi.ts
solutionC/
static/
server.ts
tsconfig.json
Problem:
My problem lies with typescript complaining about es6 import statements. From within say solutions/solutionA/static/def.ts, I cannot do
import abc from "./abc.js"
even though this is correct in-browser, as I have set the root /static as a static folder.
Is there any way I can indicate to typescript via tsconfig.json or other means, that I would like it to also search in a particular directory for said files (in this case, the root /static?). I do not want the resulting js files to have their import paths changed, as /abc.js will indeed be valid due to the express middleware.
Current situation:
As the imports are correct when loaded in browser, my solution is currently "working". The issue lies in the fact both visual studio code and tsc rightfully complain of the incorrect import path. This is a fairly recent refactoring, the merging of like solutions to stop splintering. It seemed like a good idea, only now my entire project is littered with errors.... Other people are going to be working on my solution eventually, and I don't want to give them something with copious amounts of worrying warnings.

Building monorepo babel-transpiled node JS application with dependencies

I am working on a project that is hosted as a monorepo. For simplification purposes let's say that inside there are three self-explanatory packages: server, a webapp client and library. The directory structure would be something like the following:
the-project
packages
server
src
webapp
src
library
src
All packages employ flow type notation, use a few >ES5 features and, for this reason, go through babel transpilation. The key difference is that transpilation of the webapp package is done via webpack, whereas server employs a gulp task that triggers script transpilation through the gulp-babel package. library is transpiled automatically when web is built.
Now, the problem I have is that for server to build, babel requires library to be built first and its package.json to specify its (built) main JS source file so its transpiled artifacts can be included. As you can imagine, this would quickly become problematic if the project were to contain multiple libraries that are actively being developed (which it does), as all would require building, including any dependent packages (like server in this simple case).
As an attempt to overcome this annoyance, I initially thought of using webpack to build the server, which would take care of including whatever dependencies it requires into a bundle, but I ran into issues as apparently webpack is not meant to be used on node JS applications.
What strategies are available for building a node JS application requiring Babel transpilation, such that the application's source files as well as any dependencies are built transparently and contained in a single output directory?
Annex A
Simplified gulp task for transpilation of scripts, as employed by server.
return gulp
.src([`src/**/*.js`], { allowEmpty: true })
.pipe(babel({ sourceMap: true }))
.pipe(gulp.dest('dist'));
As can be seen above, only server's own source files are included in the task. If src were to be changed to also include library, the task would emit the dependencies' artifacts in server's own output directory and any require('library') statements within would attempt to locate the built artifacts in packages/library and not packages/server/dist, thus resulting in import failures.
First of all, I am not sure what your server is doing. If it is doing a database connection or some calculations then I would not recommend it to be built by webpack. Whereas If your server is just doing Server-Side Rendering and making some API calls to other servers then I would recommend it to be bundled using webpack.
A lot of projects follow this philosophy. For example, you can take a look at something similar, I have done in one of my personal projects [Blubus]. Specifically, you might be interested in webpack-server-config. And also you can take a look at how big projects like spectrum does it.

why react should usually be a prod dependency and not dev-dependency

Sorry if I'm missing some obvious thing, but I can't seem to understand why react (or react-dom) should be a dependency and not dev-dependency on most projects..
Usually the src is written in es6 and stored in /src or /client for example, and when someone want to build the project for prod he will create /build or /dist where the finalize bundle.js will seat (using webpack and such). from there (at prod) it simply a web server which serve regular js (the bundle) and html file.
Do I miss somthing?
I dont understand why will I want react on the prod (unless going for SSR of course)..
Thank you very much!
dependencies are required to run, devDependencies only to develop, e.g.: unit tests, Coffeescript to Javascript transpilation, minification, ...
React is a dependency because it is included in the final build.
In case of a React App, all your JSX is converted to a syntax similar to React.createElement and hence you would require your App to have React during run time as well. Similary methods like setState and lifecyle functions are all executed during run-time.
As a matter of fact react is a library that has exposed some methods and APIs to access and manipulate DOM.
Consider this similar to jquery or express where you add it in the production build because they are being used during run time.
When creating a react app, things like babel, webpack etc which are only used to create a bundle would be dev-dependencies as once the packaged bundle is generated it need not be generated during run time of application
I had the same question and found this article that explains it well.
To summarize, it shouldn't matter where you put the react dependencies since Webpack will bundle them into a self-contained file and the code will run fine in either case. However, separating development and production dependencies allows for a better communication to other developers for the purpose of these dependencies.
A dependency is something that is imported in the src/ or client/ module like you mentioned. The code that you run depends on it and hence is required in the production bundle.
If it were something like Babel it could be a devDependency because:
It is not imported in source code.
It is a transpiler and works on code in compile time
But that is not the case with React. Functions like setState or lifecycle hooks are being executed in run time, meaning the library has to be present during run time.
React could very well be listed as a peer dependency is some of the popuar libraries. This is because we assume that all projects that are going to use this library are going to have React installed. Like consider the case of react-bootstrap. It can only be run in react projects, so we include react as peer dependency reducing the overhead of installing it.
If you need a framework that would disappear in compile time, take a look at Svelte.

Packaging requirejs optimized files in war

In a large web application, I'm using requirejs amd modules so that the scripts themselves are modular and maintainable. I have the following directory structure
web
|-src
|-main
|-java
|-resources
|-webapp
|-static
|-scripts
|-styles
|-images
|-static-built //output from r.js. not checked into git
|-WEB-INF
During build js and css are optimized using r.js into static-built folder. Gradle is the build tool.
Now the problem: The jsps refer to the scripts in static/scripts folder and this is how i want when working locally. However when building war, I want the static files to be served from static-built folder. The important thing is the source jsp should not have to change to serve the optimized files from static-built folder.
Two options that I have are: a) the gradle build while making war should include static-built instead of static. b)include static-built in addition to static and using tuckey urlrewrite pick the resouce from static-built rather than static.
What best practices are the community following in similar scenarios?
We've setup the server to have a runtime profile (dev, qa, prod, etc) read from a system property which determines some settings based on it. When running in production profile we serve the optimized files from the WAR. In development we serve the non-minified and non-concatenated files directly from the filesystem outside the application context.
Files are structured according to the official multipage example.
Configuring serving files depends on your chosen backend solution. Here's an example for spring.
Alternatively, r.js can generate source maps and those will help with development as well.
Not sure if this question is outdated already, but I had a kind of similar problem.
I had similar project structure, but with the only difference - I've split the project into 2 modules:
one of them (let's call it service) was java-module for back-end
the second one contained only js and other stuff related to front-end (let's call it ui).
Then in Gradle build 'assemble' task of the service depends on 'assemble' task of ui AND another custom task called 'pre-assemble'. This 'pre-assemble' task was copying the optimized js files to place where I wanted them to be.
So, basically, I've just added another task that was responsible for placing all the optimized js files in the proper place.

Resources