Rewriting sass url when building project - javascript

I'm using webpack-dev-server during development and have a public folder as content base containing: index.html, img/**.*.jpg.
During development in my sass file i reference images as:
background-image: url('img/background.jpg');
This works fine during development since webpack-dev-server is serving the images in the public folder.
But when I build the project and generate a dist folder that is later going to be deployed to a test server I need to rewrite all the urls in the sass files since they aren't going to be served from the root of the webserver. In my case I would like to rewrite the previous css rule as:
background-image: url('folder1/folder2/folder3/img/background.jpg');
Is this possible?

Not exactly. I would recommend you instead keep your paths relative to the folder you're currently in. For instance, have an assets folder that has both img, sass, etc. Then, your paths could be relative to the assets root as opposed to needing to traverse to a separate build folder. That way it won't matter if you're in build, dist or otherwise.
For example:
|assets
|-sass
|--my_styles.scss
|--SUBSTYLES
|---my_substyles.scss
|-img
|--my_img.png
and your paths would then be:
url(../img/my_img.png) //For my_styles.scss
and
url(../../img/my_img.png) //For my_substyles.scss
Otherwise, you'll need to keep a separate variable file per server/build type that defines a ROOT_PATH variable and appends it in your SASS. Something along the lines of
url($ROOT_PATH + 'img/my_img.png')
which could always be wrapped in a mixin to be used more easily.

I solved this with environment variables using sass-loader.
module.exports = {
...
sassLoader: {
data: "$env: " + process.env.NODE_ENV + ";"
}
};

Related

Problem writing to file fs module, apparently the path is positioned at the root level

I'm practicing with typescript and I want to write a file using fs module but I don't know if is this a noob question or I'm doing something wrong but my project look like this:
root
-> dir (here are the js result from tsc)
-> src
--> data
---> data.json
--> service
---> service.ts
--> index.ts
-> package.json
-> tsconfig.json
And at service.ts apparently the path is:
let filePath = path.join('./','src','data','data.json') // this works
fs.writeFile(filePath, JSON.stringify(data,null,2), 'utf8', (err)=>{ if(err){ return console.log(err);}})
So I don't know why the path is positioned at the root level
If I try "../data/data.json" I get ENOENT ERROR no such file or directory
Is it ok?
Filesystem operations with relative paths always use the Current Working Directory - a concept explained here: https://en.m.wikipedia.org/wiki/Working_directory
When you run Node.js, you do so while being in a particular directory. For example, scripts such as npm start are usually executed in the root-level directory of a repository/project - this causes all relative paths to resolve starting from there. Note, however, that this may be different in production - it is possible for Docker, PM2, systemd, or any other tool to run your script while being in a different working directory (this can often be configured).
To inspect your current working directory in Node.js, use https://nodejs.org/api/process.html#processcwd
It is also possible to build paths relative to the directory of the JS file. This tutorial shows various examples on how to do that: https://www.digitalocean.com/community/tutorials/nodejs-how-to-use__dirname
It is important to remember that require() uses paths relative to __dirname, but fs resolves relative to CWD.

File Pathing in Node.js

I have a folder that looks like
Main > models > file1.ejs
|
|> routes > file2.ejs
Two require file1 from file2 the code is const variable = require("../models/file1.ejs)
Let's say I do not want to require the model relatively, why does
const variable = require("/models/file1.ejs") not work.
Isnt "/" meaning to start at the root directory?
If we have an extensive nest of folders within another, how can we avoid doing "../../../../" in our file pathing?
Additionally, why does a code in JS that looks like Comment = require("./models/comment")
work but does not work when you do Comment = require("models/comment")
Or something in ejs that looks like <%- include("partials/header") %>
<%- include("/partials/header") %> does not work.
Is there anyway to always start from the root directory during pathing? Starting with "/" seems to end up causing an error when its suppose to make my pathing start from the root directory.
For example consider the below code,
var filename = "file1.ejs";
var fullpath = __dirname + "/models/" + filename;
read the docs about __dirname here
This is how you can provide the absolute path, where the __dirname will provide you with the path until the current working directory.
Where as relative paths work as below,
For example, if you trying to access file file1.ejs which is inside models directory from other file file2.ejs which is inside directory models2 where the models2 directory is also inside models then you may provide the relative path,
ie, the folder structure is as follows,
basePath/models/file1.ejs
basePath/models/models2/file2.ejs
and access file1.ejs from file2.ejs as below,
var path = '../file1.ejs' // going one folder back and getting inside parent models directory where the file1.ejs resides
Isnt "/" meaning to start at the root directory?
No. "/" refers to your existing file directory.
Additionally, why does a code in JS that looks like Comment = require("./models/comment") work but does not work when you do Comment = require("models/comment")
"/" is how node differentiates if they should pick up locally or somewhere in your installed modules. Imagine you have Express installed in your project and you have a file express.js. Then require('./express') will import your local file but require('express') will import the installed library instead.
If we have an extensive nest of folders within another, how can we avoid doing "../../../../" in our file pathing?
I believe you will need Babel. I haven't found any good sample on the web, but here are some useful materials.
Side note, I have worked on node project with related setup, but the development experience was awful as my editor couldn't pick up the resolved path and was struggling with auto-complete and intellisense. (but I personally believe the setup way was wrong or depreciated).
Resources:
Import module from root path in TypeScript
https://www.npmjs.com/package/babel-plugin-module-resolver
https://webpack.js.org/configuration/resolve/

Electron Packager - working with relative paths

I was wondering how I would deal with relative paths within my application when using electron packager.
In my app source folder I have some json files and other files that I reference. When packaging, electron-packager creates the \resources\app directory and places all these files into that directory. This means that any relative paths I'm using during development fail in the packaged app.
I tried pre-emtping this by creating the \resources\app folder in my source directory hoping the packager would notice them and just move them directly but it created \resources\app\resources\app instead.
I have had success using __dirname along with upath to build paths to assets.
I like upath rather than path because it has a toUnix method which "replaces the windows \ with the unix / in all string params & results."
var imgPath = upath.toUnix(upath.join(__dirname, "assets","welcome.png"));

Folder path - Absolute folder path

I am trying to add static folder for a project in app.js file. Im using macOS.
app.use(express.static("public")); // will work
app.use(express.static("\public")); // will work
app.use(express.static("/public")); // wont work
Can someone tell me what is the difference between these three.
"Public" folder is in project file.
Like this --> My_project > (public, app.js, node_modules)
const express = require("express");
const bodyParser = require("body-parser");
const request = require("request");
const app = express();
app.use(bodyParser.urlencoded({extended:true}));
app.use(express.static("public"));
First, it's not clear which operating system you're using. From your second example, it looks like you're using Windows (since that's the only OS that uses the "\" character as a directory separator). My experience with node is limited to Linux, but I believe it ought to work the same with Windows...
Edit MacOS is actually a "Linux-like" OS, so the discussion of Linux below applies equally to MacOS.
So, to answer your first question about the three different "public" paths:
app.use(express.static("public")); will use the public directory relative to where you started your node application. So, if you're in the directory "src" and your "public" directory is in the "src" directory, then it will serve files from that "public" directory.
app.use(express.static("\public")); will (I think) work the same as with the previous example. This is using the Windows path separator, so this is behavior I'm not too familiar with.
app.use(express.static("/public")); will attempt to serve public files from a "public" directory located at the root of the filesystem on a Linux system. This is actually an unusual use - normally you wouldn't create a public file directory in your filesystem root. You would be more likely to use the first version (or a slightly different path specification that means the same thing, like ./public).
So your example gives three different path specifications with varying meanings on different operating systems. How can you avoid this confusion?
Node provides a solution to this kind of confusion: the path module. Specifically, path.join method is provided to construct paths that work correctly on your operating system.
One pattern which I have seen used a lot is to make sure you are getting exactly the file/directory you expect by making it relative to the current file, like so:
app.use(express.static(path.join(__dirname, 'public')));
Imagine that this is in a file called C:\development\myproject\index.js and your static assets are in C:\development\myproject\index.js. This code will wind up working like this:
app.use(express.static('C:\development\myproject\public'));
where the path is constructed via the path.join method.
And, if you switch to Linux in the future (or you have other developers working on the project on their Linux machines), the code doesn't need to be changed to update the path.
I believe,
app.use(express.static("public"));
This will serve ./public folder contents as static files. (default behaviour)
app.use(express.static("\public"));
This will also serve the ./public folder, because you are merely escaping p(like escaping " by \"). As p and escaped p are same values it will work as expected.
app.use(express.static("/public"));
This tries to serve /public folder. / without any . means root, so it will try to access your local drive root directory and check if there is a public directory inside it.
You can test this by creating a directory called public in root and making a file inside it.

How to set .next-folder in another folder?

I have my pages folder in /client folder and would like .next folder in root of project.
I have a project with the following structure:
Whereby I place pages folder under ./client/pages. Ideally, I would like to place .next folder in root of project.
Is it possible to do this?
You can use the next.config.js file to specify the output of the build.
I like to have my folder called _next to make routing easier.
module.exports = {
distDir: '_next',
};
So you could make your path traverse one level through the directory with:
module.exports = {
distDir: '../.next',
};
Although I would recommend you don't use the .next name and use the underscore instead, this will solve a lot of headaches in production.
module.exports = {
distDir: '../_next',
};
An even better solution would be to use a proxy like Nginx to handle the routing for you. So leave your _next folder in the client directory and set the root path to your client folder.

Categories