Next.js page's first paint is missing all styles - node.js

I'm using scss to style my next.js app however I noticed that all styles are missing when I preview the first paint via the network tab in google chrome.
As you can see the page is fairly simple and does not fetch any initial props. I'm suspecting that the server is for some reason not building the whole page (including styles) on the backend.
My next.config.js setup is:
const withStyles = require("#webdeb/next-styles");
module.exports = withStyles({
sass: true, // use .scss files
modules: true, // style.(m|module).css & style.(m|module).scss for module files
});

With newer nextjs versions, I don't think you need to use withStyles and similar plugins anymore.
global styles only
You can just:
install sass
install whatever css framework you're using and follow their instructions for how to include their css / scss files in your project
potentially get rid of your next.config.js file entirely if it's a simple project and all you had in the config file was css configuration stuff.
import your scss files directly into your js files (eg import '../styles/app.scss')
scoped scss styles
seems you can keep the next.config.js file, based on this workaround I found here through a google search:
const withStyles = require('#webdeb/next-styles')
module.exports = withStyles({
sass: true, // use .scss files
modules: true, // style.(m|module).css & style.(m|module).scss for module files
})

Related

Nuxt with Vuetify. CSS in HEAD tag

I was installed Nuxt via command npx create-nuxt-app with Vuetify plugin. Then I ran server via npm run dev or npm run build && npm start and in page source I see CSS styles of Vuetify in <head> tag. After some googleing I found advice add extractCSS: true, in build section of nuxt.config.js. After that when I run npm run build && npm start css files are generating and linking to pages, but I still see some CSS styling (~500 lines) in <style data-n-head="true" id="vuetify-theme-stylesheet" type="text/css">. How I can hide them to CSS file instead of displaying in <head> tag.
And how I can extract CSS when start npm run dev (pretty annoying to scroll this CSS when debug HTML layout)?
Not sure if this is exactly the same issue but I found had many lines of Vuetify colours CSS in the head of each pre-rendered html file. I eventually found https://vuetifyjs.com/en/features/theme/#variations.
When Vuetify generates your application’s theme, it creates 9 variants for each color. For majority of users, these variants are rarely used. This is an opt in feature that will be false by default in the next major version.
// src/plugins/vuetify.js
import Vue from 'vue'
import Vuetify from 'vuetify/lib'
export default new Vuetify({
theme: {
options: { variations: false },
},
})
Adding options: { variations: false } as above (along with extractCSS: true in Nuxt.config.js) got rid of all superfluous CSS in the pre-rendered html.

Vue buildt doesn't show router pages

I'm doing a webpage with Vue (Vue-bootstrap) and I'm having problems to make it works. I'm uploading the content of the dist folder after using npm run build, the project was started using `vue init bootstrap-vue/webpack my-project. I've tried to add a vue.config.js file with the next information:
module.exports = {
baseUrl: './',
//...
}
I've try several times adding this in different folders before build it but I can't make it work.
The result just show the footer, it is in:
http://thegraph.es/Citython/
and the code without this vue.config.js is in the next link:
https://github.com/MGijon/Citython/tree/master/web

How to properly load photos with Node and Webpack?

Should I be loading photos in node by importing relative paths or by referencing the file URL, and how do you properly load photos from their relative path?
Currently I'm serving static files with express:
server.use(express.static(__dirname + '/../public'));
And loading photos by referencing file URLs:
<img src='/images/tom.jpg'/>
I have a webpack configuration set up to use file-loader on (png|jpg|gif), and the webpack docs say, that with file-loader, you can import photos from relative paths (https://webpack.js.org/loaders/file-loader/#src/components/Sidebar/Sidebar.jsx):
import img from './file.png'
With this configuration (this is the config I'm using):
module.exports = {
module: {
rules: [
{
test: /\.(png|jpg|gif)$/,
use: [
{
loader: 'file-loader',
options: {}
}
]
}
]
}
}
However, when I try to import an image from it's relative path:
//import
import img from '../../public/images/tom.jpg';
//render
<img src={img}/>
I receive this error:
/Users/ryan/Desktop/Df/Coding/ryanchacon.io/node_modules/babel-core/lib/transformation/file/index.js:590
throw err;
^
SyntaxError:
/Users/ryan/Desktop/Df/Coding/ryanchacon.io/public/images/tom.jpg:
Unexpected character '�' (1:0)
1 | ����
But if I emit the 'import from relative path', start my server, and then add the relative import back, the image will load from its relative path. However, if I restart my server, the error throws again.
So instead I'm referencing the file URL to get around this error, but I'm not sure how I should properly load files from their relative path with my webpack/node configuration.
Currently, I'm running node v8.6.0, webpack v3.6.0, express v4.15.4, file-loader v1.1.5, and react v16.0.0.
In your server.js file, you're using server side rendering (which is awesome): ReactDOMServer.renderToString( <App /> ). The App component rendered on the server side is imported via the import App from './src/App'; statement. In the App.js file you have the JPG import statement: import img from '../public/hermes.jpg';.
Please notice that in this context, your node.js is not aware of any webpack bundle in your project, and node actually tries to import the '../public/hermes.jpg' file, which causes the error you're facing (node can only load JS modules).
So the question is, in fact, how to use file-loader in a universal/isomorphic manner. You can take a look at this example project: https://github.com/webpack/react-webpack-server-side-example that shows a webpack configuration for both the server and the client code. Theoretically, if you bundle your server code via webpack, when you run it, the JPG import statement would already be processed by the file loader and should not cause any problem. I have to admit that personally I do not think bundling server code is a good idea (bundling solves client side issues that are not really relevant on the server side).
If you insist using file-loader and bundling your image files into your client code, using server side webpack might be a good solution for you. If not, you can simply load the images from the /public folder.
For what it's worth, I believe that loading the images by using URLs is not only simpler, but also faster - the browser will download your lighter JS bundle (it's lighter because it does not contain encoded image files) and your code will start running earlier on, downloading the images from HTTP in a parallel, asynchronous manner.

Sails is not injecting the files within the assets folder

I just did a fresh installation of sails (v0.11.0) in my server and after checking this up and working on controllers I found that css, js and templates files included into the assets folders are not being injected to the layout, if there any reason for this to happen? I mean, it is a clean fresh sails installation....
In my quest to get SailsJS to auto-inject stylesheets into the layout file under views/layouts/layout.handlebars in my case, I've found out a couple things...
When you first create your sails app using:
sails new APPNAME --template=handlebars --verbose
note: link below explains above syntax...
Using handlebars templates in Sails.js
Go to config > views.js
It will say:
layout: 'layouts/layout.handlebars'
change to:
layout: 'layouts/layout',
Go to tasks > config > sails-linker.js
Because I'm in development mode right now I will Ctrl + f searching for:
"devStyles"
devStyles: {
options: {
startTag: '<!--STYLES-->',
endTag: '<!--STYLES END-->',
fileTmpl: '<link rel="stylesheet" href="%s">',
appRoot: '.tmp/public'
},
files: {
'.tmp/public/**/*.html': require('../pipeline').cssFilesToInject,
'views/**/*.html': require('../pipeline').cssFilesToInject,
'views/**/*.ejs': require('../pipeline').cssFilesToInject
//ADD HANDLEBARS INJECTION HERE
}
},
Notice it has .html, & .ejs types being injected but not .handlebars
add this line:
'views/**/*.handlebars': require('../pipeline').cssFilesToInject
where I commented:
//ADD HANDLEBARS INJECTION HERE
At this point you should be able to drop a .css file into assets > styles and have it auto-copied to .tmp/public/styles
run:
sails lift
in your command prompt and give it about 20 seconds or so to have the stylesheet manifest its style on whatever page you have in your routes.js
'/': {
view: 'index'
}
As you can see, I made a new .handlebars file index.handlebars and set it as my root level page. You may have to refresh the page a time or two to get the newly auto-injected CSS to show.
P.S. It appears there is no more need to append --linker when first creating a SailsJS project. Also fyi, I'm using sails version 0.11.0
Also if you run sails lift --verbose the line below is how you know the .handlebars injection is working
verbose: Grunt :: File "views/layouts/layout.handlebars" updated.
Hope this helps!
Also, when adding Handlebars Helpers they should go in a file helper.js which should be located in config > helper.js
At the top of the helper.js file I found I had to require handlebars as follows
handlebars = require('sails/node_modules/express-handlebars/node_modules/handlebars');

Overcome differences in node and browserify path resolving

I'm writing a module for a react app that needs to be included on both the backend and frontend.
At some point in my code, I'm requiring some svg file (for which I use a browserify module, but this has nothing to do with the question).
For example I have in my ./src/js/components/tools/svg.js the following bit of code:
// ...
var BACKEND = /* code to detect if this is running on browser or on node */;
var svg;
if ( BACKEND ) {
svg = require("./../../../icon/" + this.props.icon + ".svg");
} else {
svg = require("./src/icon/" + this.props.icon + ".svg");
}
// ....
I use browserify's require option to require all the svg files at bundle-time:
browserify({
paths: ['./src/icon'],
})
.transform(/* svg tansformer */)
.require(glob.sync("./src/icon/*.svg")) // <-- svg's get added here
.add("./src/main.js"); // main entry point
However this conflicts with how node resolves the filenames. It cannot find ./src/icon/ from ./src/js/components/tools/svg.js.
This is why I have to guard the require with the BACKEN clause. This breaks my eyes though and I would like to just be able to write:
var svg = require('./src/icon/' + this.props.icon + '.svg');
I've tried two things so far:
fix node to find ./src/icon
I can use export NODE_PATH=`cwd` to allow node to look for src/icon from ./. This allows me to write:
var svg = require('src/icon/' + this.props.icon + '.svg');
in the backend. But, since browserify only accepts paths that start with ./ (thus, ignoring src/icon) this will not resolve on the frontend.
fix browserify to use ../../../icon/
Haven't got this to work either because of the same reason: browserify only accepts paths that start with ./.
It's considered bad practice doing conditional requires when using Browserify because it can't evaluate the code at "compile time" and will always attempt to load all the files.
To load different files in the browser environment than on node is easy:
Add a "browser" field to your package.json that points to the browser main file. Use "main" for the node main file. Then just require the module.
You can do the same thing with sub folders within your project. Just add a package.json file with "private": true and both, the main and the browser properties and require the folder path.

Resources