Flash of unstyled content in Gatsby when using global style sheet - css

I am working on a gatsby project where everything is working fine, except for when I load any page of the website as there is a flash of unstyled content for like a second. The issue persists in all the pages and my research on fixing this issue revealed this to be a persisting issue when working with styled-components. My project does not use styled components as there is one global style sheet that is shared across the project as the style sheet is loaded in the gatsby-browser.js.
code in the config below. Can anyone assist me here?
require('dotenv').config({
path: `.env.${process.env.NODE_ENV}`
});
module.exports = {
siteMetadata: {
title: 'name of site',
siteUrl: `https://lffff.com`,
description: `some description.`,
author: 'name',
image: 'image link'
},
pathPrefix: '/v2',
plugins: [
'gatsby-transformer-sharp',
'gatsby-plugin-react-helmet',
`gatsby-plugin-sharp`,
`gatsby-transformer-sharp`,
{
resolve: `gatsby-source-filesystem`,
options: {
name: `images`,
path: `${__dirname}/src/images/`
}
},
{
resolve: 'gatsby-source-contentful',
options: {
spaceId: process.env.CONTENTFUL_SPACE_ID,
accessToken: process.env.CONTENTFUL_ACCESS_TOKEN
}
},
{
resolve: 'gatsby-plugin-react-svg',
options: {
rule: {
include: /assets/
}
}
},
{
resolve: `gatsby-plugin-manifest`,
options: {
name: `GatsbyJS`,
short_name: `GatsbyJS`,
start_url: `/`,
display: `standalone`,
icon: 'src/images/5f8e0f3ace9452d1a7fbe65b_LP_Logo_Square.png'
}
}
]
};
this is what is in gatsby-browser.js
import './src/styles/globalStyles.css';

You are using prefixed paths at:
pathPrefix: '/v2',
In development (gatsby develop) paths don't need to be prefixed, however, during the build and server process (gatsby build && gatsby server) it's a needed specification
If you are building a path manually, you can use withPrefix helper function that prepends your path prefix in production.
Change your build and serve commands to:
gatsby build --prefix-paths
And:
gatsby serve --prefix-paths
If you are not using the pathPrefix, just remove it from your configuration and keep your commands as at the beginning.

Related

Tailwind css classes not showing in Storybook build

I am trying to build my storybook with tailwind css. When running build-storybook the components are rendered with the tailwind classes. Unfortunately, when I build storybook and run the create build storybook-static with npx http-server storybook-static the classes are not loaded into the stories and the components are displayed not styled.
This is a repro repo of my project:
https://gitlab.com/ens.evelyn.development/storybook-issue
This is my main.js :
const path = require('path')
module.exports = {
"stories": [
"../src/components/**/**/*.stories.mdx",
"../src/components/**/**/*.stories.#(js|jsx|ts|tsx)"
],
"addons": [
"#storybook/addon-links",
"#storybook/addon-essentials",
{
name: '#storybook/addon-postcss',
options: {
postcssLoaderOptions: {
implementation: require('postcss'),
},
},
},
"#storybook/addon-actions",
"storybook-tailwind-dark-mode"
]}
My Projectstructure looks like this:
.storybook
src
components
subdir
Button
index.tsx
button.stories.js
styles
index.css (<-- tailwindcss file)
Any hints or advice is very appreciated.
UPDATE: My original answer could be useful to others, so I'll leave it for reference. However, in this case, the problem was in tailwind.config.js.
Change
purge: {
mode: 'all',
content: [
'./src/components/**/**/*.{ts, tsx}'
],
},
to
purge: ['./src/**/*.{js,jsx,ts,tsx}'],
ORIGINAL:
Just tested it out and storybook builds as expected for me. I think the key difference in our configurations is that I am not making changes to Storybook's webpack config in main.js. Rather, I am using #storybook/addon-postcss for postcss#^8 (required for tailwind#^2):
// main.js
module.exports = {
...
addons: [
...
{
name: '#storybook/addon-postcss',
options: {
postcssLoaderOptions: {
implementation: require('postcss'),
},
},
},
],
};
I specify the necessary plugins in a postcss.config.js (in my project root):
// postcss.config.js
module.exports = {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
}
It's also worth noting that I import Tailwind directly in Storybook's preview.js instead via my own css file:
// preview.js
import 'tailwindcss/tailwind.css';
export const parameters = {...}
Hopefully, making those changes will get Tailwind working for you.
For comparison (see comments below), here are the contents of my build storybook-static directory:
The above solutions will not work for Tailwind version > 3.0 because of JIT compiler.
Solution 1: Easy solution
in .storybook/preview.js file add this line to compile tailwind generated css files like this -
import '!style-loader!css-loader!postcss-loader!tailwindcss/tailwind.css';
Here tailwindcss/tailwind.css is the tailwind css file. Look, important is I've to add !postcss-loader! to compile tailwind generated css.
You can add also your custom scss file like this if any -
import '!style-loader!css-loader!sass-loader!../src/scss/style.scss';
Here ../src/scss/style.scss is custom scss file.
For most of the people this will work in Tailwind version > 3.0 without any issue.
Solution 2: Kinda Hack solution
Create a custom styled element in preview page
import tailwindCss from '!style-loader!css-loader!postcss-loader!sass-loader!tailwindcss/tailwind.css';
const storybookStyles = document.createElement('style');
storybookStyles.innerHTML = tailwindCss;
document.body.appendChild(storybookStyles);
Hope, this will help for new Tailwind users who are working in Tailwind greater than v3.0.
I had a similar problem. My problem was solved by adding:
import "../src/index.css"; to .storybook/preview.js
The following configuration will enable so Tailwind generate CSS as new tailwind classes are added to the markup in dev mode (hot reload).
In summary, I don't think #storybook/addon-postcss works with Tailwind JIT and Storybook hot reload, and the workaround is to use the postcss-loader webpack loader.
Install these deps:
#storybook/builder-webpack5
#storybook/manager-webpack5
postcss-loader
webpack (must be version 5)
// .storybook/main.js
const path = require("path");
module.exports = {
stories: ["../src/**/*.stories.mdx", "../src/**/*.stories.#(js|jsx|ts|tsx)"],
addons: [
"#storybook/addon-links",
"#storybook/addon-essentials",
"#storybook/addon-interactions",
// {
// name: "#storybook/addon-postcss",
// options: {
// postcssLoaderOptions: {
// implementation: require("postcss"),
// },
// },
// },
],
framework: "#storybook/react",
core: {
builder: "webpack5",
},
webpackFinal: (config) => {
config.module.rules.push({
test: /\.css$/,
use: [
{
loader: "postcss-loader",
options: {
postcssOptions: {
plugins: [require("tailwindcss"), require("autoprefixer")],
},
},
},
],
include: path.resolve(__dirname, "../"),
});
return config;
},
};
// .storybook/preview.js
import "../styles/globals.css";
export const parameters = {
actions: { argTypesRegex: "^on[A-Z].*" },
controls: {
matchers: {
color: /(background|color)$/i,
date: /Date$/,
},
},
};
// postcss.config.js
module.exports = {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
};
if you using storybook with TSdx and tailwind css you should be able to import a CSS into components
To be able to import your CSS into components, you will need to tell
TSDX how to include it with your code. For that, you will need to
install rollup-plugin-postcss (as TSDX uses rollup).
Create a CSS file in your src directory which we will use in any
component in which we want to use Tailwind.
Alright, so now let's add rollup-plugin-postcss:
yarn add -D rollup-plugin-postcss
TSDX is fully customizable and you can add any rollup plugin, but be aware that it overrides the default behavior
Now you'll create a
tsdx.config.js
// tsdx.config.js
const postcss = require('rollup-plugin-postcss');
module.exports = {
rollup(config, options) {
config.plugins.push(
postcss({
config: {
path: './postcss.config.js',
},
extensions: ['.css'],
minimize: true,
inject: {
insertAt: 'top',
},
})
);
return config;
},
};
This is giving a postCSS path, which tells it what files you want it to run on. The minimize key is to allow you to minimize the output. The most important key here is the "inject". you set it to "top" to tell postCSS where inside the of our page the CSS will be inserted. It's paramount for Tailwind as it needs to have the utmost priority of any other stylesheet.
Next, for part 2, you will create a tailwind.css (can be named anything else) file under the src directory and paste this in:
// src/tailwind.css
#tailwind base;
#tailwind components;
#tailwind utilities;
Add the CSS import statement to your component
// src/Thing.tsx
import React, { FC, HTMLAttributes, ReactChild } from 'react';
// ! Add the CSS import statement !
import './tailwind.css`;
// ...
// we'll add some Tailwind classes on our components to test
export const Thing: FC<Props> = ({ children }) => {
return (
<div className="flex items-center justify-center w-5/6 m-auto text-2xl text-center text-pink-700 uppercase bg-blue-300 shadow-xl rounded-3xl">
{children || `the snozzberries taste like snozzberries`}
</div>
);
};
For those who are still having this problem and is using postcss >= 8, I suggest you to do as following.
Add this to tailwind.config.js
// eslint-disable-next-line #typescript-eslint/no-var-requires
const path = require("path")
module.exports = {
content: [path.join(__dirname, "./src/**/*.(js|jsx|ts|tsx)")],
theme: {
extend: {},
},
variants: {}
plugins: [],
}
Add this to preview.js
import "!style-loader!css-loader!postcss-loader!tailwindcss/tailwind.css"
export const parameters = {
actions: { argTypesRegex: "^on[A-Z].*" },
controls: {
matchers: {
color: /(background|color)$/i,
date: /Date$/,
},
},
}
This has helped me fix the problem and I hope it can help you too
I couldn't work this out and the above answered didn't work for me, so I eventually just set my build-storybook script to run tailwind itself after the build. package.json scripts looked like this in the end:
"build-storybook": "build-storybook -s public && $(npm bin -g)/tailwindcss -i storybook-static/static/css/main.*.chunk.css -o storybook-static/static/css/main.*.chunk.css -m",
Bit of a mess, but $(npm bin -g)/ here uses my globally installed (npm i -g tailwindcss) version of tailwindcss as the version installed to the project wasn't working in builds for me.
-i and -o specifies the input and output files, and -m minifies the output.
I can foresee this causing problems if more than one CSS file gets built (maybe using storybook-static/static/css/**/*.css would work instead?), but this might help someone just get something working.
When you try to create a storybook while using Tailwind CSS, you will notice that the CSS is not being applied. There is a simple solution that has helped me.
Your preview.js should be like.
export const parameters = {
actions: { argTypesRegex: "^on[A-Z].*" },
controls: {
matchers: {
color: /(background|color)$/i,
date: /Date$/,
},
},
};
And you will need to add the following line in the preview.js to fix it.
// Add the below import line
import "!style-loader!css-loader!postcss-loader!tailwindcss/tailwind.css";
export const parameters = {
actions: { argTypesRegex: "^on[A-Z].*" },
controls: {
matchers: {
color: /(background|color)$/i,
date: /Date$/,
},
},
};
However this will be a temporary fix.
To get this resolved completely, you will need to add the below mentioned package.
yarn add -D #storybook/addon-postcss
For reference, click here
How to add postcss
The solutions mentioned above worked but only partially.
I was facing 2 issues:
If I added new classes to stories then tailwind was not adding corresponding styles associated with the classes.
Hot reloading wasn't working.
Solution:
Add the path to the stories folder in the tailwind.config.js file.
module.exports = {
content: [
"./pages/**/*.{js,ts,jsx,tsx}",
"./components/**/*.{js,ts,jsx,tsx}",
"./stories/**/*.{js,ts,jsx,tsx}", //needed to make hot reload work with stories
],
theme: {},
plugins: [],
}

NextJS/Webpack does not build node_module dependency with internal css

I have a couple of issues with a NextJS project that I believe might be solvable with a well built webpack configuration (However I am fairly new to webpack).
I am using NextJS 8.0.3 with #zeit/next-css 1.0.2-canary in my local NextJS project, and I have a couple of npm installed dependencies that use css internally (styled reusable components).
The issue that I'm having is that I can't build or export my application because I get a CssSyntax error, and if I use next-plugin-transpile-modules it will build the installed node_modules dependencies but it won't load the css, because it does not build it.
This is the next.config.js file content, if you find the webpack part you will notice that it just uses the basic css-loader.
module.exports = withBundleAnalyzer(withCss({
poweredByHeader: false,
cssModules: false,
// assetPrefix: APP_PREFIX, // This actually sets the path for getting static files somewhere else?*
publicRuntimeConfig: { // Will be available on both server and client
// pathPrefix: APP_PREFIX,
cache: {
static: {
cdn: 3600,
browser: 3600
},
dynamic: {
cdn: 600,
browser: 0
}
}
},
webpack: (config, { defaultLoaders }) => {
// Fixes npm packages that depend on `fs` module
config.module.rules.push({
test: /\.css$/,
use: [
'css-loader',
'style-loader',
]
});
config.node = { fs: 'empty' }
// console.log(config)
return config
},
// bundle analyzer
analyzeServer: ["server", "both"].includes(process.env.BUNDLE_ANALYZE),
analyzeBrowser: ["browser", "both"].includes(process.env.BUNDLE_ANALYZE),
bundleAnalyzerConfig: {
server: {
analyzerMode: 'static',
reportFilename: '../bundles/server.html'
},
browser: {
analyzerMode: 'static',
reportFilename: '../bundles/client.html'
}
}
}))
My most immediate question is, what webpack loader or what pipeline configuration can I use so that webpack actually builds the css that is imported from the jsx dependency, and then build the component properly so that it's internal css and of course it's functionality are fully built.

Gatsby/Wordpress - .env credentials not working

I am working with the gatsby-source-wordpress plugin
If I hard code my API keys/secret into my Gatsby.config, everything works fine, but I want to add these as .env variables so that I can .gitignore for deployment, and this is where things are breaking.
At the root of my directory, I have a .env file which looks like this
CLIENT_SECRET=10987654321
CLIENT_ID=123456
USER=secret#secret.com
PASS=mypassword1
I'm then try to access these in gatsby.config, like this
require('dotenv').config({
path: `.env.${process.env.NODE_ENV}`
});
module.exports = {
siteMetadata: {
title: 'Gatsby Default Starter',
},
plugins: [
{
resolve: 'gatsby-source-wordpress',
options: {
baseUrl: 'myurl.com',
protocol: 'http',
hostingWPCOM: true,
useACF: false,
auth: {
wpcom_app_clientSecret: `${process.env.CLIENT_SECRET}`,
wpcom_app_clientId: `${process.env.CLIENT_ID}`,
wpcom_user: `${process.env.USER}`,
wpcom_pass: `${process.env.PASS}`,
},
},
},
{
resolve: `gatsby-plugin-emotion`,
},
'gatsby-plugin-react-helmet',
{
resolve: `gatsby-plugin-manifest`,
options: {
name: 'gatsby-starter-default',
short_name: 'starter',
start_url: '/',
background_color: '#663399',
theme_color: '#663399',
display: 'minimal-ui',
icon: 'src/images/gatsby-icon.png', // This path is
relative to the root of the site.
},
},
'gatsby-plugin-offline',
],
}
which is returning the following errors when I run either gatsby develop or gatsby build
source and transform nodesThe server response was "400 Bad Request"
source and transform nodesThe server response was "403 Forbidden"
Inner exception message : "User cannot access this private blog."
No routes to fetch. Ending.
So, the issue is the .env variables don't seem to be pulling through properly, but I can't see a reason why they wouldn't be? Is there anything I've missed in setting this up?
Gatsby doesn't know which plugin you mean (see How to use) and your overall syntax is wrong. The plugins is an array for example.
module.exports = {
plugins: [
{
resolve: "gatsby-source-wordpress",
options: {
auth: {
wpcom_app_clientSecret: process.env.CLIENT_SECRET,
wpcom_app_clientId: process.env.CLIENT_ID,
wpcom_user: process.env.USER,
wpcom_pass: process.env.PASS,
}
}
}
]
}
This should work assuming that you also define the other necessary fields mentioned in the README.

Using relative paths in SASS background images

I'm trying to get background images to work in my Angular project's SASS when I don't know where the application root will be. For example, the app's home page could be:
localhost:9000/home
or
localhost:9000/foo/home
or
localhost:9000/bar/home
I figured I could address this by just making the paths in my background-image properties relative, like this:
div {
background-image: url("assets/smiley.png");
}
However, that doesn't work. When I compile the app, it can't find the assets. In the console, it says:
Error: Can't resolve './assets/smiley.png'
It gives me this same message whether my background-image url value starts with ./ or not. But even ./ I imagine should work.
What DOES work is if I hard-code the path into the background-image property, making the path ABSOLUTE, like so:
div {
background-image: url("/foo/assets/smiley.png");
}
However, that's not an option, since I don't know if the app root will be at /foo/ or /bar/ or something else.
Another thing that works is using the --base-href option of ng build to hard-code the path, like so:
ng build --base-href /foo/
But if possible, I'd really like to accomplish this with code changes that don't involve passing parameters to the ng build command on a build-by-build basis.
Here is my Webpack Config located at node_modules/#angular/cli/models/webpack-config.js. Is that the right file? Sorry if it's not - I'm pretty unfamiliar with webpack:
/**
* Adapted from angular2-webpack-starter
*/
const helpers = require('./config/helpers'),
webpack = require('webpack');
/**
* Webpack Plugins
*/
const ProvidePlugin = require('webpack/lib/ProvidePlugin');
const DefinePlugin = require('webpack/lib/DefinePlugin');
const LoaderOptionsPlugin = require('webpack/lib/LoaderOptionsPlugin');
module.exports = {
devtool: 'inline-source-map',
resolve: {
extensions: ['.ts', '.js']
},
entry: helpers.root('ng2-translate.ts'),
output: {
path: helpers.root('bundles'),
publicPath: '/',
filename: 'ng2-translate.umd.js',
libraryTarget: 'umd',
library: 'ng2-translate'
},
// require those dependencies but don't bundle them
externals: [/^\#angular\//, /^rxjs\//],
module: {
rules: [{
enforce: 'pre',
test: /\.ts$/,
loader: 'tslint-loader',
exclude: [helpers.root('node_modules')]
}, {
test: /\.ts$/,
loader: 'awesome-typescript-loader?declaration=false',
exclude: [/\.e2e\.ts$/]
}]
},
plugins: [
// fix the warning in ./~/#angular/core/src/linker/system_js_ng_module_factory_loader.js
new webpack.ContextReplacementPlugin(
/angular(\\|\/)core(\\|\/)(esm(\\|\/)src|src)(\\|\/)linker/,
helpers.root('./src')
),
new webpack.LoaderOptionsPlugin({
options: {
tslintLoader: {
emitErrors: false,
failOnHint: false
}
}
})
]
};

How to integrate WordPress into Webpack?

I developed a website front-end using HTML/CSS, JavaScript and Sass or Scss. I used NPM.
I need to put that website into WordPress. I already installed WordPress and put that folder with all my assets(HTML/CSS, JS, Sass etc..) into theme folder.
Now, what do I do now? How do I connect all of this?
I know it's possible because I have worked on a site like this before at work, but not sure how to do it from the ground up.
Webpack -> WordPress. I will watch the files with NPM or webpack, but the hosting will be doing with MAMP - that's how I did it at work anyways.
What should I do?
This is the website code if anything: https://github.com/AurelianSpodarec/lovetocodefinal
PS, no WordPress API or any stuff like that, but just as I wrote above.
I found a solution to this.
It's simple. You need to compile everything and put it in the folders that will be used by WordPress and do WordPress magic to get the styles with functions.
I have made this here: https://github.com/AurelianSpodarec/Webpack-to-WordPress-Starting-Template
It's not perfect, but a good starting point for those who are looking on using Webpack with WordPress.
Old Question, but just had the same one myself. I just built a light Wordpress-Webpack starter. You can use it to build Wordpress-Themes and it will build Scss and copy PHP etc. into the destination of your Themes. It uses Browsersync for easier development. You have complete separation of dev and build :) Maybe this can still help in future. Regards, Fabian
Link: https://github.com/fabiankuhn/webpack-wordpress
Extract from Main Build config (Paths):
const themeName = 'test-theme'
const themePath = '/Users/<Username>/<repos>/Test/webpack/wordpress/wp-content/themes'
/*
* Main Config
*/
module.exports = {
entry: './webpack-entry.js', // Main Entry: Is included in functions.php
output: {
filename: 'main.js', // Is included in functions.php
// Set Path of Wordpress Themes ('.../wp-content/themes') as absolute Path
path: themePath + '/' + themeName + '/assets',
},
Extract from Wordpress webpack config:
const merge = require('webpack-merge');
const common = require('./webpack.common.js');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const CopyPlugin = require('copy-webpack-plugin');
const BrowserSyncPlugin = require('browser-sync-webpack-plugin')
// This Config Exports the FIles with Source Maps for Wordpress Development
module.exports = merge(common, {
mode: 'development',
devtool: 'inline-source-map', // Use Source-Maps for Debug
plugins: [
// Plugin to Reload Browser According to Proxy 127.0.0.1:8080 (Wordpress PHP)
new BrowserSyncPlugin({
host: 'localhost',
port: 3000,
proxy: '127.0.0.1:8080',
files: [
{
match: [
'**/*.php',
'**/*.js',
'**/*.css',
],
},
],
notify: false,
},
{
reload: true,
}),
// Extract CSS
new MiniCssExtractPlugin({
filename: '[name].css',
chunkFilename: '[id].css',
}),
// Copy all Files to Entry Output Path except Github, Webpack and
// Original Sources (Before Webpack Processing)
new CopyPlugin([
{
from: '../',
to: '../',
ignore: [
'_webpack/**',
'assets/**',
'.git/**',
],
},
]),
],
module: {
rules: [
{
// Listen for Sass and CSS
test: /\.(sa|sc|c)ss$/,
use: [
{
loader: MiniCssExtractPlugin.loader,
options: {
},
},
// Source Map shows Path in Chrome for Testing
{ loader: 'css-loader', options: { sourceMap: true, importLoaders: 1 } },
{ loader: 'sass-loader', options: { sourceMap: true } },
],
},
],
},
});

Resources