Node.js and project structure - javascript

I am working on a new project with Node.js, Express, Socket.io and the MySQL module and being a beginner with those technologies, I have a few questions about structuring the project and good practices.
Right now, my code is structured as follow:
├── node_modules
├── package.json
├── server.js
├── server.socket.live.js # Socket.io namespace
├── server.database.js # For database configuration and connection pool
├── server.database.resources.js # Model for the 'resources' table
├── server.route.live.js
└── ...
For the current state of the project, it works well enough, but the code grows fast and a sole directory will make the code hard to navigate and maintain.
So I've been trying to figure out a way to structure my code with the following rules:
I need global files that I can include from everywhere (for example: the database and models).
The routes and other sub-components must be (and are) independant to each other.
Node must be able to correctly cache each files, so different paths ('./database.js' and '../database.js') are out of the question.
If possible, avoid requires from parent directories.
With that in mind, I came up with this solution:
├── package.json
├── node_modules
| └── ...
├── server.js
├── server
| ├── node_modules
| | ├── database
| | | ├── package.json
| | | ├── database.js
| | | ├── resources.js
| | | └── ...
| ├── socket
| | ├── live.js # With live subfolder if file grows too big
| | └── ...
| ├── routes
| | ├── live.js # With live subfolder if too many sub-routes
| | └── ...
In theory it works great: with a structure like this I could easily add new "global" modules in server/node_modules, and new routes or socket namespaces, as long as they are independant from each other.
So my question: would that work in practice, or is there a better way to do it? Will Node be able to require the files in server/node_modules with good caching? How do I include the server/node_modules subfolder in my git repository (while still ignoring the root node_modules)?
With many thanks!

Related

How to segregate page components into several `/pages` directories on a Next.js app

I recently started my first project with Next.js and since then my pages directory has grown a lot. Now I want to separate my pages and group them into modules, ending up with something like 'src/modules/*/pages/*'.
Researching the topic I came accross exportPathMap, a function that I can include in my next.config.js file and then map custom paths to my pages, but it seems like I'd need to add a new path for every page I create, which is not ideal. I want to give to Next a single expression, something like 'src/modules/*/pages/*', and let it resolve the pages and routes for me (like you would do in a ormconfig.json file to map entities when using TypeORM).
I suppose I could group my page components directly inside pages, like pages/a-module/*, but I also have components, hooks and other logic that I'd like to segregate into modules. I could also try using Node's fs to iterate through my project file structure and map the the page folders, but I'd like to avoid that if possible.
You could use symlinks. You would need one for each module, but not one for each nested path within the module. Your directory structure would look like:
├── modules
│ ├── bar
│ │ └── pages
│ │ ├── first.js
│ │ └── second.js
│ └── foo
│ └── pages
│ ├── first.js
│ └── second.js
├── pages
│ ├── _app.js
│ ├── bar -> ../modules/bar/pages
│ ├── foo -> ../modules/foo/pages
│ ├── index.js
Which would end up with routes:
/bar/first
/bar/second
/foo/first
/foo/second
I'm not sure what that buys you, though, really. Now your modules folder will have the same clutter that pages used to. You don't have to have all of the component content in the files in pages. It could be as simple as:
// pages/foo/first.js
import FirstContent from '../../modules/FirstContent'
export default function First() {
return <FirstContent />
}
As #Roman Mkrtchian mentioned, you're not supposed to do so. My suggestion is that, if you want to organize your files into modules like me, creating a file structure similar to this one:
src
├── modules
│ ├── foo
│ | └── pages
| | ├── one
| | | ├── index.jsx
| | | └── styles.js <- For `styled-components`; could be a css file
| | └── two
| | ├── index.jsx
| | └── styles.js
| └── bar
| └── pages
| └── three
| ├── index.jsx
| └── styles.js
├── shared
└── ...
You should take another approach. As #erich2k8 said, you don't need all of the component content to be in the files inside /pages, you could create the same structure above, but add /pages directly to src:
src
├── modules
├── shared
└── pages
├── foo
| ├── one.jsx
| └── two.jsx
└── bar
└── three.jsx
And inside src/pages/foo/one.jsx, for instance, you'd import src/modules/foo/pages/one, like so:
import OneContent from '../../modules/foo/pages/one';
const One = () => <OneContent />;
export default One;
Yes, you'd still need to create a new file for each page you create inside /modules, but it spares you from a really bad time messing with Next behavior.
This is not permitted by the Next.js team on purpose for reasons explained in this post and in the posts referenced there.
You may read some of the discussions before deciding if you really want to hack the files structure to do it anyway.

Dynamic source for vue-i18n custom block

I'm using vue-i18n and I was wondering if there is a way to dynamically change the source file of <i18n> to match the locale language.
For each vue component I have a folder with my different translations :
├── myComponent
| └── lang
| ├── en.json
| ├── fr.json
| └── index.vue
In my index.vue I'd like to do something like :
<i18n src='./lang/' + $i18n.locale + '.json'></i18n>
Is it possible ?
UPDATE:
So apparently it is not possible for now.

What is the proper way to import js, css, scss files to webpack?

I'm new to webpack and I am trying to use material-dashboard (https://www.creative-tim.com/product/material-dashboard) in my project.
Actually, I installed using npm install (https://www.npmjs.com/package/material-dashboard)
So I got this structure in my ./node_modules/material-dashboard:
material-dashboard/
├── assets/
| ├── css/
| | ├── bootstrap.min.css
| | ├── material-dashboard.css
| | └── demo.css
| ├── js/
| | ├── bootstrap-notify.js
| | ├── bootstrap.min.js
| | ├── chartist.min.js
| | ├── demo.js
| | ├── jquery-3.1.0.min.js
| | ├── material-dashboard.js
| | └── material.min.js
| ├── sass/
| | ├── md
| | └── material-dashboard.scss
| └── img/
|
├── documentation/
├── examples/
In their example to import they just use link tags like:
<!-- CSS Files -->
<link href="../assets/css/bootstrap.min.css" rel="stylesheet" />
<link href="../assets/css/material-dashboard.css" rel="stylesheet"/>
<link href="css/demo-documentation.css" rel="stylesheet" />
But I'm using webpack so I've tried to import using require in my entry file (app.ts)
require('material-dashboard/assets/css/material-dashboard.css');
after adding in my webpack.config
loader: isTest ? 'null' : "style-loader!css-loader"
Apparently it works, I'm not quite sure. But there are 3 css files, 7 js files and 2 .scss files.
I don't want to to import file by file, of course there is a better way.
I would like to know what is the proper way to import in webpack js/css/scss files to use in a project?
Thanks.
very easy man
for js file use
import 'the_name_of_npm_package';
for 'css' file use
require('the_name_of_npm_package/../../../the_file.css');
NOTE : if you still find problems u can use Vue webpack template with vue cli there are alot of tuts on utube that template is easy for begginers in webpack it has every loader and config you need .

Understanding r.js options w/grunt & backbone and relative paths

I'm trying to figure out how to use r.js. I keep getting errors thrown such a module path does not exist, or files getting dumped where they shouldn't be.
I've got a single page application that is integrated with wordpress. I've adopted this backbone boilerplate for my general structure, although I've set things up quite different. My file structure is shown below.
.Theme Folder
├── _assets
| ├── _application
| | ├── css
| | ├── fonts
| | ├── img
| | ├── _js
| | | ├── main.js //this is my require.js config file
| | | ├── _app //here's where the boilerplate structure comes into play
| | | ├── collections
| | | ├── models
| | | ├── routers
| | | ├── templates
| | | ├── views
| | | ├── libs
| | | ├── utilities
| | ├── scss
| | ├── video
| └── build //Concatenated application directory mirror
| └── gruntfile.js
| └── bower.json
| └── package.json
To save the heartache of deciphering my gigantic grunt file. Basically I originally set it up so that everything gets conatenated, uglified, and compiled into the build folder. I created a simple task for r.js to just test things out. I get an error saying my lodash library cannot be found (first path in my main.js file). It thinks lodash is in assets/lodash.js it's ignoring my baseUrl property in my main.js (require.js configuration) it's actual location is assets/application/js/libs/lodash.js. My requirejs task is below:
requirejs: {
compile: {
options: {
baseUrl: "./",
mainConfigFile: "application/js/main.js",
name: "./application/js/main",
out: "./build/js/optimized.js"
}
}
}
I'm having the hardest time figuring out what exactly rjs is doing. When I expect it to work it's not looking for the files in the right directory. When I configure it to find the right files it copies my entire assets folder and dumps it into my build folder... Which has caused a lot of confusion as to what all r.js is doing and what it wants me to input for it's options.
This is the error I am currently getting:
>> Error: ENOENT, no such file or directory
>> 'path-to-theme-folder-here/assets/libs/lodash.js'
>> In module tree:
>> application/js/main.min
It seems to me with the description you give, this should work:
requirejs: {
compile: {
options: {
baseUrl: "application/js/",
mainConfigFile: "application/js/main.js",
name: "main",
out: "build/js/optimized.js"
}
}
}

Uglifyjs files in debug folder and move them to release folder

I want to uglifyjs my files in my debug/js folder and move them to release/js folder. My bash script is in the root directory of debug and release:
.
├── release.sh
├── debug
| ├── js
| | ├── a.js
| | ├── b.js
| | ├── c.js
├── release
| ├── js
This is what I have got so far:
for file in "debug/js/*"
do
fileName=$(basename "$file")
uglifyjs $file > "release/js/$fileName.js"
done
Unfortunately, this does not work at all. It just creates one *.js file in release/js, which is not what I want. What am I doing wrong?
This is what I actually want:
...
├── release
| ├── js
| | ├── a.js
| | ├── b.js
| | ├── c.js
From the bash man page
Enclosing characters in double quotes preserves the literal value of
all characters within the quotes, with the exception of $, `, \, and,
when history expansion is enabled, !.
So moving the * outsides double quotes, "debug/js/"* or removing the double quotes all together, since there are no spaces or other special characters in the path, would work.

Categories

Resources