Next.js with FortAwesome and SSR - javascript

I am building a Next.js application and looking for an icon package that works with its SSR paradigm.
After trying a few libs, I'm now working with FortAwesome/react-fontawesome, which looks promising.
The problem is when the page loads the icons are large (unstyled) and then suddenly they are styled properly. I'm trying to figure out how to get these to style server-side.
I've seen folks talk about importing a stylesheet provided by FortAwesome:
import '#fortawesome/fontawesome-svg-core/styles.css';
However, I'm unsure which file(s) this should be done in and also, Next complains when I try this:
[ error ] ./node_modules/#fortawesome/fontawesome-svg-core/styles.css
1:8 Module parse failed: Unexpected token (1:8) You may need an
appropriate loader to handle this file type, currently no loaders are
configured to process this file
I've looked at the CSS plugin, but this also seems like a red herring.
How can I get the font-awesome icons in this package to be styled on the server with Next.js?

React-fontawesome has added a section on how to get FontAwesome working with Next.js.
https://github.com/FortAwesome/react-fontawesome#nextjs
Create an ./pages/_app.js file in your project
import React from 'react'
import App, { Container } from 'next/app'
import { config } from '#fortawesome/fontawesome-svg-core'
import '#fortawesome/fontawesome-svg-core/styles.css' // Import the CSS
config.autoAddCss = false // Tell Font Awesome to skip adding the CSS automatically since it's being imported above
class MyApp extends App {
render() {
const { Component, pageProps } = this.props
return <Component {...pageProps} />
}
}
export default MyApp
or using a function component:
import { config } from '#fortawesome/fontawesome-svg-core'
import '#fortawesome/fontawesome-svg-core/styles.css' // Import the CSS
config.autoAddCss = false // Tell Font Awesome to skip adding the CSS automatically since it's being imported above
export default function MyApp({ Component, pageProps }) {
return <Component {...pageProps} />
}

There are definitely a few ways to take this problem. I solved it in my project by importing the icons I needed directly into my React app. So no Font Awesome libraries sit on the client-side, just the rendered SVGs.
import { FontAwesomeIcon } from '#fortawesome/react-fontawesome'
import { faAdobe } from '#fortawesome/free-brands-svg-icons/faAdobe'
...
return (
<FontAwesomeIcon icon={faAdobe} />
)
Font Awesome also provides a page to discuss other methods: server-side-rendering

I'm going to put this as an answer, because it's a way, however I feel like there is a better solution out there, so I will not accept this one.
I created a static/css folder, then copied the css file referenced in the question
cp node_modules/#fortawesome/fontawesome-svg-core/styles.css static/css/fortawesome.css
Then in _document.js I load the file via link tag:
<link
rel="stylesheet"
type="text/css"
href="/static/css/fortawesome.css"
/>
I would consider this a stop-gap solution. One issue obviously is that when the underlying library updates I would need to copy over the latest version of the css file manually.

I had this same issue and fixed it by manually inserting Font Awesome's CSS into styles which I know will get SSR'ed correctly.
I use styled-components, which is easy to set up with Next.js SSR, and here's how I did it:
import { createGlobalStyle } from "styled-components";
import { config, dom } from "#fortawesome/fontawesome-svg-core";
// Prevent FA from adding the CSS
// (not that it was doing it in the first place but might as well)
config.autoAddCss = false;
// Add the FA CSS as part of Global Styles
const GlobalStyles = createGlobalStyle`
${dom.css()}
`;

Here is what I have tried so far to fix this issue in my project:
Installation of #zeit/next-css, #zeit/next-sass [I need sass too.]
Installation of fontawesome packages & import CSS
Installation of #zeit packages
Install required packages:
npm i --save #zeit/next-css
npm i --save #zeit/next-less
npm i --save #zeit/next-sass
then update next.config.js file such as below that will support CSS import which fix the issue of loading correct styles upon loading:
const withCSS = require('#zeit/next-css')
const withLess = require('#zeit/next-less')
const withSass = require("#zeit/next-sass");
module.exports = withLess(withCSS(withSass({
webpack(config, options) {
config.module.rules.push({
test: /\.(png|jpg|gif|svg|eot|ttf|woff|woff2)$/,
use: {
loader: 'url-loader',
options: {
limit: 100000
}
}
});
return config
}
})));
Installation of fontawesome packages & import CSS
Install required packages:
npm i --save #fortawesome/fontawesome-svg-core
npm i --save #fortawesome/free-solid-svg-icons
npm i --save #fortawesome/react-fontawesome
Then you can use following code within your pages extending React.Component located under pages directory:
import { FontAwesomeIcon } from '#fortawesome/react-fontawesome';
import { library } from '#fortawesome/fontawesome-svg-core';
import { fas } from '#fortawesome/free-solid-svg-icons'
import '#fortawesome/fontawesome-svg-core/styles.css';
library.add(fas);
Then this is the way you can use fonts:
<FontAwesomeIcon icon={["fas", "user-tie"]} />
I may be wrong.

Related

how to import mathjax in vue as local dependency?

im using vue-mathjax in my project and in the readme it says to use cdn of mathJax
works fine with the CDN version
im need to use mathJax(v. 2.7.2) as local as dependency for my project but dont know how to import it with the correct configurations
how do yout set the configuration same as with the cdn version?
CDN
<script src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.2/MathJax.js?config=TeX-AMS_HTML"></script>
Local import after installing with npm
//main.js
import '../node_modules/mathjax/MathJax?config=TeX-AMS_HTML'
error
Uncaught SyntaxError: Unexpected token '<'
repo - https://github.com/qwtfy/mathjax-test
If you're able to switch to the new version 3, here are the steps assuming you already have vue-mathjax.
Install MathJax from npm: npm install mathjax#3
Move the MathJax's es5 directory to a public directory: mv node_modules/mathjax/es5/ src/assets/mathjax/
Import the component config you want, for example:
import '../assets/mathjax/es5/tex-chtml.js';
If you must stick with version 2.7.x, you'll need to do the following. In my testing, it was less stable.
Install MathJax 2.7.9 from npm: npm install --save mathjax#2.7.9
Move MathJax.js (located at node_modules/mathjax/MathJax.js) to a public directory like assets.
Move TeX-AMS_HTML.js (located at node_modules/mathjax/config/TeX-AMS_HTML.js) to the same public diretory.
Import both files inside your component, in order:
import '../assets/MathJax.js'
import '../assets/TeX-AMS_HTML.js';
Here it is working for me:
Full single file component example using v3 and vue-mathjax.
<template lang='pug'>
div
b-container(style='width: 40%')
b-textarea(v-model='formula' cols='30' rows='10')
p output
vue-mathjax(:formula='formula')
</template>
<script lang="ts">
import { Component, Vue } from 'vue-property-decorator';
import { VueMathjax } from 'vue-mathjax';
import '../assets/mathjax/es5/tex-chtml.js';
#Component({
components: {
'vue-mathjax': VueMathjax,
},
})
export default class HelloWorld extends Vue {
formula = '$$x = {-b \\pm \\sqrt{b^2-4ac} \\over 2a}.$$';
}
</script>
Documentation of these steps can be found here and here.

Storybook with Tailwind and Emotion setup

I have the following storybook component:
import {storiesOf} from "#storybook/react"
import * as React from "react"
import styled from "#emotion/styled"
import tw from "#tailwindcssinjs/macro"
const Button = styled.button(tw`
relative
w-64 min-w-full
`)
const ButtonStyled = ({children}) => <Button>{children}</Button>
storiesOf("Button", module).add("with text", () => (
<ButtonStyled>this is a button </ButtonStyled>
))
without the styled version and embedding the css classes straight into the className it works. The moment I introduce the styled version I get the following error:
Although the node_module package is there it doesn't seem to find it.
If you want to use Tailwind with Emotion, now you can use Twin macros.
You can start by checking out this example:
https://github.com/ben-rogerson/twin.examples/tree/master/cra-emotion
When you're done installing that, run this command in the project root:
npx sb init
It will install Storybook for you with the ideal settings.
Having done that, you'll have a ready-to-use emotion-powered Storybook.

React import all scss rules from a file into a component

I'm trying to add the whole scss file into a React component.
I tried using styleName props but not succeed
import React from 'react'
import Calendar from 'calendar'
import { calendarStyles } from './calendar.scss'
const CalendarShift = () => <Calendar styleName={calendarStyles}/>
export default CalendarShift
Would like to know if its posible to "spread" all the scss rules from calendar.scss into Calendar component
What you should do is to import the file and then use the class names like you will use them normally in a react component.
import React from 'react'
import Calendar from 'calendar'
import './calendar.scss'
const CalendarShift = () => <Calendar className="calendar"/>
export default CalendarShift
Note that you need a webpack loader for scss to work along with your react app.
In the case you wanted to use all the styles (class names) within your calendar component, you can still import the file in the file above and use the class names in the Calendar.
Another solution will be using a postcss sass extension to convert styles into objects so you can use them in object notation. Check this out https://github.com/postcss/postcss-scss
Easy peasy! Just use the github postcss-scss plugin and you can install it like this:
npm --save install postcss-scss
Or, if you prefer yarn:
yarn add --dev postcss-scss
You can check the github page for this plugin to get more information about it.
After installing, you can use your SCSS in object notation and use it like this:
const CalendarShift = () => <Calendar style={myStyle} />

How to load CSS module with next.js

I'm trying to use the react-datepickermodule in my react App, but I'm having a hard time trying to load the css module of react-datepicker. I'm using next.js to render my app on server side.
I tried to implement a css loader provided by next to solve this kind of issue, but I got an error trying to build my app:
error
My component.js file:
import DatePicker from "react-datepicker";
import 'react-datepicker/dist/react-datepicker-cssmodules.css';
My nex.config.js file:
const withImages = require('next-images');
const withCSS = require('#zeit/next-css');
module.exports = withImages(
withCSS({
cssModules: true
})
);
Can you please tell me what is wrong with my imports or config ? Or what the 'minimize' property (displayed on the error message) means ?
Thanks a lot
EDIT: I ended up by importing css directly from
<link href="/static/react-datepicker.css" rel="stylesheet" />. Original post
Your css modules must end with .module.css.
To use CSS Modules, import a CSS file named *.module.css from any component. src
Import this way instead:
import styles from 'react-datepicker/dist/react-datepicker-min.module.css'
Try using Compose in your config file
I think you need to compose your plugins like so
// ... other imports
const compose = require('next-compose');
module.exports = compose([
withImages(),
withCss(),
{
webpack: (config) => {
/**some special code */
return config
}
}
]);
Details about the plugin can be found here
Your code is fine!
Instead of importing CSS into a component, try to import it into the page you wanted to use it on.
Next.js supports only custom page CSS imports.

Critical dependency warning when using react-pdf

I'm trying to display a pdf on a react application and i get the following warning:
/node_modules/react-pdf/node_modules/pdfjs-dist/build/pdf.js
Critical dependency: require function is used in a way in which dependencies cannot be statically extracted
Vscode tells me this under the import function.
Could not find a declaration file for module 'react-pdf'
Already tried running npm install, npm install react-pdf and reinstalling the package
import React, { Component } from 'react';
import { Document } from 'react-pdf';
import sample from 'file location'
export default class viewer extends Component {
render() {
return (
<div>
<Document
file={sample}
onLoadSuccess={this.onDocumentLoadSuccess}
>
</Document>
</div>
);
}
}
Displays:
"Failed to load PDF file" in the browser
This code will display your pdf file, but issue will display in IDE console.
import { Document, Page, pdfjs } from "react-pdf";
pdfjs.GlobalWorkerOptions.workerSrc = `//cdnjs.cloudflare.com/ajax/libs/pdf.js/${pdfjs.version}/pdf.worker.js`;
In my case I'm using webpack 4 and it's not supportted yet.
If you build project it will work fine.
My full workaround.
Create a file at the root called config-overrides.js and it should contain the following:
module.exports = function override(config) {
config.module.rules[0].parser.requireEnsure = true
return config
};
After that npm i react-app-rewired to you app and change your build function in package.json to read react-app-rewired build/react-app-rewired start.
That should do it for now.

Categories

Resources