NestJS and Handlebars are not showing images - handlebars.js

I am trying to use images in my handlebars templates which are used for emails. The only problem is that the images are not showing. I have tried several ways to solve the problem, but nothing helped.
main.ts configs:
app.useStaticAssets(join(__dirname, '..', 'src', 'static'))
app.setBaseViewsDir(join(__dirname, '..', 'src', 'static', 'templates'))
app.setViewEngine('hbs')
Folder structure:
-src
--static
---img
----image1.png
----image2.png
---templates
----email1.hbs
----email2.hbs
How image would be used in the template:
<img src="/static/img/logo.png" alt="logo">
In email it looks like this:
https://ci4.googleusercontent.com/proxy/IhSgHQ3zXQ7Wh6MMxDAzkCjjFuvjZF3OI_Ru5CEQg3dGnin7xXJdUfjVTIg8Ag=s0-d-e1-ft#http:///static/img/logo.png

With reference to Nest.js official documentation, first install hbs module and then set the App module according to the code below and access your static files as in the second part of the code below.
import { Module } from '#nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { ServeStaticModule } from '#nestjs/serve-static';
import { join } from 'path';
#Module({
imports: [
ServeStaticModule.forRoot({
rootPath: join(__dirname, '..', 'static'),
}),
],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}
Using static files in your templates:
<div>
<img src='/img/image1.png' alt='' />
</div>
Take out the static directory from the src directory and place it next to it:
-src
-static
--img
---image1.png
---image2.png
--templates
---email1.hbs
---email2.hbs

Related

NextJS images are not shown using "export" script

I have a simple NextJs app.
When I'm running the app on a localhost everything seems to work fine - All the images are shown as expected
When I use this script: next build && next export
and browse to my local build, I don't see the images, but instead its "alt" text
The way I import an image:
import React from 'react';
import Image from 'next/image';
import someImage from '../../../public/images/some-image.png';
const Main = () => {
return (
<div>
<Image
src={someImage}
alt="Some Image"
placeholder="blur"
/>
</div>
}
next.config.js
/** #type {import('next').NextConfig} */
const configuration = {
reactStrictMode: true,
eslint: {
dirs: ['./src'],
ignoreDuringBuilds: true,
},
images: {
loader: 'akamai',
path: '',
},
};
module.exports = configuration;
My code design:
Environment:
"next": "13.1.6",
"react": "18.2.0",
Moreover, I tried to use a normal img tag and it causes the same problem.
If anyone here faces the same issue ill appreciate any help!
Refer to this page:
https://nextjs.org/docs/messages/export-image-api
You are attempting to run next export while importing the next/image component using the default loader configuration.
However, the default loader relies on the Image Optimization API which is not available for exported applications.
So, when running static NextJS app with export you cannot use NextJS optimization, as it should run in your non-existent server. You should use cloud solution (https://nextjs.org/docs/api-reference/next/image#loader-configuration) or remove optimization:
module.exports = {
images: {
unoptimized: true,
},
}
(https://nextjs.org/docs/api-reference/next/image#unoptimized)
When importing something statically from the public folder it already knows youre inside it. You only need the following import:
import someImage from 'images/some-image.png';

Configuring Vanilla TS Vite project to keep CSS files separated

I am trying to set up a basic (css) library with vanilla TS and Vite 4.
I want to have a main js and css file at the top level so you can import the whole thing in one go. I also want to have component level imports where you can chose to just import the components js + css. The combined css and JS files are working fine; and the individual component JS file is working fine too.
Currently I'm running into the problem where I can't seem to keep an isolated version of the CSS files next to the JS files after bundling. My build is currently creating :
I've gone over the docs of both Vite and Rollup but I can't seem to figure out how to do the same to my CSS as I'm doing to my JS.
dist
--components
----button
------button.js
--main.css
--main.js
My preferred output would be:
dist
--components
----button
------button.js
------button.css
--main.css
--main.js
In my `main.ts` I'm importing:
import './style.scss'
import './tokens.scss'
import './components/button/button.scss'
vite.config.js
import { defineConfig } from 'vite'
import { resolve } from 'path'
export default defineConfig({
build: {
cssCodeSplit: false,
manifest: true,
rollupOptions: {
output: {
assetFileNames: () => 'main[extname]',
}
},
lib: {
formats: ['es'],
entry: {
main: resolve(__dirname, 'src/main.ts'),
button: resolve(__dirname, 'src/components/button/button.ts')
},
name: 'CSSFramework',
fileName: (_, fileName) => fileName === 'main' ? '[name].js' : 'components/[name]/[name].js',
},
},
});
Thanks in advance !

Next.js Global CSS cannot be imported from files other than your Custom <App>

My React App was working fine, using global CSS also.
I ran npm i next-images, added an image, edited the next.config.js, ran npm run dev, and now I'm getting this message
Global CSS cannot be imported from files other than your Custom <App>. Please move all global CSS imports to pages/_app.js.
Read more: https://err.sh/next.js/css-global
I've checked the docs, but I find the instructions a little confusing as I am new to React.
Also, why would this error happen now? Do you think it has anything to do with the npm install?
I've tried to remove new files I've added along with their code, but this doesn't fix the problem. I've also tried what the Read more: suggests.
My highest tier component.
import Navbar from './Navbar';
import Head from 'next/head';
import '../global-styles/main.scss';
const Layout = (props) => (
<div>
<Head>
<title>Bitcoin Watcher</title>
</Head>
<Navbar />
<div className="marginsContainer">
{props.children}
</div>
</div>
);
export default Layout;
My next.config.js
// next.config.js
const withSass = require('#zeit/next-sass')
module.exports = withSass({
cssModules: true
})
My main.scss file
#import './fonts.scss';
#import './variables.scss';
#import './global.scss';
my global.scss
body {
margin: 0;
}
:global {
.marginsContainer {
width: 90%;
margin: auto;
}
}
The thing I find the weirdest is that this error came without changing anything to do with CSS, or Layout.js, and it was previously working?
I've moved my main.scss import to the pages/_app.js page, but the styles still aren't coming through. This is what the _app.js page looks like
import '../global-styles/main.scss'
export default function MyApp({ Component, props }) {
return <Component {...props} />
}
Use the built-in Next.js CSS loader (see here)
instead of legacy #zeit/next-sass.
Replace #zeit/next-sass package with sass.
Remove next.config.js. Or do not change CSS loading in it.
Move the global CSS as suggested in the error message.
Since Next.js 9.2 global CSS must be imported in Custom <App> component.
// pages/_app.js
import '../global-styles/main.scss'
export default function MyApp({ Component, pageProps }) {
return <Component {...pageProps} />
}
To add styles only to a specific component or page you can use built-in support of CSS modules. (see here)
For example, if you have a component Button.js you can create a Sass file button.module.scss and include it in the component.
Next.js stops complaining when your file has module in naming, e.g., changing import '../global-styles/main.scss'; to import '../global-styles/main.module.scss'; would fix the warning and you could have your styles in the global-styles, or for example, in your component.
No extra dependencies/configurations in next.config.js is required.
You can replace the opinionated (and overly-complex?) NextJs CSS loaders with your own. Here's a simple one for global css:
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
module.exports = {
reactStrictMode: true,
webpack: (config, { buildId, dev, isServer, defaultLoaders, webpack }) => {
// Find and remove NextJS css rules.
const cssRulesIdx = config.module.rules.findIndex(r => r.oneOf)
if (cssRulesIdx === -1) {
throw new Error('Could not find NextJS CSS rule to overwrite.')
}
config.module.rules.splice(cssRulesIdx, 1)
// Add a simpler rule for global css anywhere.
config.plugins.push(
new MiniCssExtractPlugin({
experimentalUseImportModule: true,
filename: 'static/css/[contenthash].css',
chunkFilename: 'static/css/[contenthash].css',
})
)
config.module.rules.push({
test: /\.css$/i,
use: !isServer ? ['style-loader', 'css-loader'] : [MiniCssExtractPlugin.loader, 'css-loader'],
})
return config
},
}
Add this to your _app.js
import '../styles/globals.css'
For me the problem was because I had used two module.exports in my next.config.js file like this
const withPlugins = require('next-compose-plugins')
const sass = require('#zeit/next-sass')
const css = require('#zeit/next-css')
const nextConfig = {
webpack: function(config){
config.module.rules.push({
test: /\.(eot|woff|woff2|ttf|svg|png|jpg|gif)$/,
use: {
loader: 'url-loader',
options: {
limit: 100000,
name: '[name].[ext]'
}}
})
return config
}
}
module.exports = withPlugins([
[css],
[sass, {
cssModules: true
}]
], nextConfig)
module.exports = {
env: {
MONGO_URI = 'your uri'
}
}
. 1I modified it to change the export module like this.
const nextConfig = {
webpack: function(config){
config.module.rules.push({
test: /\.(eot|woff|woff2|ttf|svg|png|jpg|gif)$/,
use: {
loader: 'url-loader',
options: {
limit: 100000,
name: '[name].[ext]'
}}
})
return config
},
env: {
MONGO_URI: "your uri"
}
}
2then I deleted the second module.exports
This node package provides a perfect solution for it. You can find it here
Steps to fix it:
1. Add package:
npm install next-remove-imports
or
yarn add next-remove-imports
2. Add this wrapper variable inside your next.config.js
const removeImports = require('next-remove-imports')({
test: /node_modules([\s\S]*?)\.(tsx|ts|js|mjs|jsx)$/,
matchImports: "\\.(less|css|scss|sass|styl)$"
});
All it is doing is re-enabling global styling import rule for tsx|ts|js|mjs|jsx files
3. Wrap your next config export with this next-remove-imports wrapper. Something like this:
module.exports = removeImports((nextConfig)
4. Now restart your react app and you will be able to import CSS files inside any ts|js|js|jsx|mjs file or component.
Try to include ".module" in your scss file name.
Change main.scss to main.module.scss
Example:
import styles from './todolist-profile-info.module.scss'
You did not need to do anything inside of next.config.js.
Let's assume you are using a global css like Bootstrap, meaning it contains css that is meant to be applied to your entire application and all the different pages inside of it.
Global css files have to be wired up to NextJS in a very particular fashion.
So inside of the pages/ directory you need to create _app.js.
It's critical that the file be named _app.js.
Then at the top of that file you would import Bootstrap css in the following manner:
import 'bootstrap/dist/css/bootstrap.css';
Then you would add the following:
export default ({ Component, pageProps }) => {
return <Component {...pageProps} />;
};
So what is going on in that code?
Well, behind the scenes, whenever you try to navigate to some distinct page with NextJS, NextJS will import your component from one of the different files inside your pages/ directory.
NextJS does not just take your component and show it on the screen.
Instead it wraps it up inside of its own custom default component and that is referred to inside of NextJS as the App.
What you are doing by defining the _app.js is to define your own custom app component.
So whenever you try to visit a route inside a browser or your root route, NextJS is going to import that given component and pass it into the AppComponent as the Component prop.
So Component there is equal to whatever components you have in the pages/ directory. And then pageProps is going to be the set of components that you are intending to pass to your files inside of pages/.
So long story short, this thing is like thin wrapper around the component that you are trying to show on the screen.
Why do you have to define this at all?
Well, if you ever want to include some global css to the project, Bootstrap being a global css for example, you can only import global css into the _app.js file.
It turns out that if you try to visit other components or other pages, NextJS does not load up or even parse those files.
So any css you may have imported inside there will not be included in the final HTML file.
So you have a global css that must be included on every single page, it has to be imported into the app file because it's the only file that is guaranteed to be loaded up every single time a user goes to your application.
Don't forget that in addition to importing the css inside of _app.js, you also have to run an npm install bootstrap in your terminal.
You can read more on this here:
https://nextjs.org/docs/messages/css-global
For me, i got this error because I had used improper naming for my project's parent folder, had used special characters in it,
like project#1,
after removing special chars, and changing the folder name to like project-1, the error got away.
In my case there was typo in navbar.module.css
I've written navbar.moduile.css
you must for every component css/scss write navbar.module.css/scss/sass.Next js doesnt compile navbar.css/scss/sass. If hope my answer helps you !.

How to add global style to angular 6/7 library

I was trying to add global styles in the same way like in angular app, but it totally does not work.
My libraries' name is example-lib, so I added styles.css to /projects/example-lib/. I added styles in main angular.json file:
...
"example-lib": {
"root": "projects/example-lib",
"sourceRoot": "projects/example-lib/src",
"projectType": "library",
"prefix": "ngx",
"architect": {
"build": {
"builder": "#angular-devkit/build-ng-packagr:build",
"options": {
"tsConfig": "projects/example-lib/tsconfig.lib.json",
"project": "projects/example-lib/ng-package.json",
"styles": [
"projects/example-lib/styles.css" <!-- HERE
],
},
...
But when I tried build library using command:
ng build example-lib
I got error:
Schema validation failed with the following errors:
Data path "" should NOT have additional properties(styles)
I guess that is the other way to add global styles in separate library. Anyone can help me?
I have a workaround for this. Just create the root component of your library without view encapsulation and all its styles will be then global.
my-library.component.ts
import { Component, OnInit, ViewEncapsulation } from '#angular/core';
#Component({
selector: 'lib-my-library',
templateUrl: './my-library.component.html',
styleUrls: ['./my-library.component.scss'],
encapsulation: ViewEncapsulation.None
})
export class MyLibraryComponent implements OnInit {
constructor() { }
ngOnInit() {
}
}
my-library.component.html
<!-- html content -->
my-library.component.scss
#import './styles/core.scss';
Now your my-library.component.scss and core.scss are global
styles/core.scss
body {
background: #333;
}
core.scss is optional, I just like to keep the root files clean.
Update: In case you want your mixins and variables too, then follow this answer.
As #codeepic already pointed out, there is currently a standard solution.
In ng-package.json add
"assets": ["./styles/**/*.css"]
The provided paths should be the paths to your files. At the same time, they will be the paths inside your /dist folder.
On build, the files will be copied to /dist. Users of your library will be able to add them to their global styles as follows.
/* styles.css */
#import url('node_modules/<your-library-name>/styles/<file-name>');
This way you can copy any type of files.
P.S. When used with CSS, do not forget that you can create an index.css file that can be imported just like node_modules/<your-library-name>/styles.
From Compiling css in new Angular 6 libraries:
install some devDependencies in our library in order to bundle the css:
ng-packagr
scss-bundle
ts-node
Create css-bundle.ts:
import { relative } from 'path';
import { Bundler } from 'scss-bundle';
import { writeFile } from 'fs-extra';
/** Bundles all SCSS files into a single file */
async function bundleScss() {
const { found, bundledContent, imports } = await new Bundler()
.Bundle('./src/_theme.scss', ['./src/**/*.scss']);
if (imports) {
const cwd = process.cwd();
const filesNotFound = imports
.filter(x => !x.found)
.map(x => relative(cwd, x.filePath));
if (filesNotFound.length) {
console.error(`SCSS imports failed \n\n${filesNotFound.join('\n - ')}\n`);
throw new Error('One or more SCSS imports failed');
}
}
if (found) {
await writeFile('./dist/_theme.scss', bundledContent);
}
}
bundleScss();
Add _theme.scss inside the /src directory of the library that actually contains and imports all the css that we want to bundle.
Add postbuild npm script to run the css-bundle.ts
Include it in the styles tag in your Application in the angular.json
From this issue solution
Install cpx and scss-bundle as Dev dependencies to your package.json. Then add the following entries in your package.json "scripts" property:
"scripts": {
...
"build-mylib": "ng build mylib && npm run build-mylib-styles && npm run cp-mylib-assets",
"build-mylib-styles": "cpx \"./projects/mylib/src/lib/style/**/*\" \"./dist/mylib/style\" && scss-bundle -e ./projects/mylib/src/lib/style/_style.scss -d ./dist/mylib/style/_styles.scss",
"cp-mylib-assets": "cpx \"./src/assets/**/*\" \"./dist/mylib/assets\"",
...
}
Replace "mylib" with your real library name and then just run in your terminal build-mylib. That would compile your scss assets to your dist folder.
You use this global styles in your actual Angular project just import them in your angular.json file within your project settings:
"styles": [
"src/styles.scss",
"dist/my-shiny-library/_theme.scss"
],
(use dist if your project is in the same workspace, or node_moduled if its an imported library)
1- be sure you are putting your styles inside the library
example:
projects/your-lib-name/assets/styles.css
2- then in your ng-package.json (in the lib for sure) put the assets rule
{
"$schema": ... ,
"dest": ... ,
> "assets": [
> "./assets/*"
> ],
"lib": ...
}
3-
in your application, you can use this asset
"styles": [
"../your-lib-name/assets/styles.css"
]
this is a tutorial

Trouble adding Bootstrap 4 CSS with Webpack 4 in ReactJS SpringBoot Application

I am getting an error where webpack is not able to resolve the bootstrap 4 css which is sitting in the node_modules directory. I have looked at a number of tutorials around webpack 4 and bootstrap 4 but I am thinking it is not in the same folder structure.
I've also tried changing the import bootstrap css trying to change the directory to push it to the node_modules directory but that does not seem to work.
Error log from Spring Tool Suite
[INFO] ERROR in ./src/main/resources/static/js/app.js
[INFO] Module not found: Error: Can't resolve 'bootstrap/dist/css/boostrap.min.css' in 'C:\sourcecode\personal-website\src\main\resources\static\js'
[INFO] # ./src/main/resources/static/js/app.js 26:0-46
webpack.config.js
var path = require('path');
module.exports = {
entry: './src/main/resources/static/js/app.js',
performance: {
hints: false
},
output: {
path: __dirname,
filename: './src/main/resources/static/built/bundle.js'
},
module: {
rules: [
{
test: /\.js$/,
exclude: /(node_modules)/,
loader: 'babel-loader',
query: {
presets: ['#babel/react', '#babel/env']
}
},
{
test: /\.css$/,
include: /stylesheets|node_modules/,
use: [ "style-loader", "css-loader" ]
}
]
}
};
app.js
import 'bootstrap';
import React from 'react';
import ReactDOM from 'react-dom';
import 'bootstrap/dist/css/boostrap.min.css';
import Landing from './components/Landing';
class App extends React.Component {
render() {
return (
<div className="container">
<Landing />
</div>
);
}
}
ReactDOM.render(
<App />,
document.getElementById('react-app')
);
I'm not sure what your folder structure is like. But, I believe everything is relative to the location of the file where you're importing bootstrap's css from.
Given the folder structure below
sourceCode
|--node_modules
|--bootstrap
|--dist
|--css
|--bootstrap.min.css
|--routes
|--src
|--main
|--resources
|--static
|--app.js
|--dist
|--views
if you're importing bootstrap's CSS stylesheet in the app.js script, it would go like:
import '../../../../node_modules/bootstrap/dist/css/bootstrap-min.css';
The double period (..) means you're moving one step up the folder structure/tree.
You did say you've tried changing your import. But, I based my answer on what you've shown.
On the other hand, try taking a look at VS Code then check out the Path Intellisense extension. It'll help you with those imports. Happy coding :)

Resources