How to load CSS module with next.js - javascript

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.

Related

Overwrite an existing plugin JS in Shopware 6

I am currently trying to overwrite a javascript file from an existing plugin.
I've been following the documentation but I am struggling with the path for the JS class to overwrite.
In the docs is an example code:
import CookiePermissionPlugin from 'src/plugin/cookie/cookie-permission.plugin';
export default class MyCookiePermission extends CookiePermissionPlugin {
}
So I implemented the following code:
import QuantityField from 'src/plugin/FilterRangeSlider/filter-range-slider.plugin';
export default class ExampleQuantityField extends QuantityField {
This code does not work for me, since the original file is in the vendor directory and my plugin is in the custom directory. When trying to compile (eg bin/build-storefront.sh) I receive the following error message:
Module not found: Error: Can't resolve 'src/plugin/FilterRangeSlider/filter-range-slider.plugin' in '<project root>/custom/plugins/ExampleProductFilter/src/Resources/app/storefront/src/filter-range-slider'
Any idea how I can import that class as stated in the docs?
Node.js provides a bunch of in-built file-system functionalities. The __dirname points to the root directory.
So, this should work.
import QuantityField from `${__dirname}/vendor/store.shopware.com/mmeesrangesliderpro/src/Resources/app/storefront/src/script/filter-range-slider.plugin`
My current solution is not really clean...
import QuantityField from '../../../../../../../../../vendor/store.shopware.com/mmeesrangesliderpro/src/Resources/app/storefront/src/script/filter-range-slider.plugin';
Isnt there any plugin root variable or something similar?
There is - I believe - no easier way to accomplish this.
If each plugin would extend the webpack config as described in
https://developer.shopware.com/docs/guides/plugins/plugins/administration/extending-webpack
const path = require('path');
module.exports = () => {
return {
resolve: {
alias: {
MmeesRangeSliderPro: path.join(__dirname, '..', 'src')
}
}
};
};
The alias could be used instead of the Plugin Root.
But this is not the case, so the following is not working:
import QuantityField from 'MmeesRangeSliderPro/plugin/FilterRangeSlider/filter-range-slider.plugin';
You can add a console.log(webpackConfig) to the bottom of Resources/app/storefront/webpack.config.js to validate this.
alias: {
src: '/home/user/example/projects/example.de/vendor/shopware/storefront/Resources/app/storefront/src',
assets: '/home/user/example/projects/example.de/vendor/shopware/storefront/Resources/app/storefront/assets',
jquery: 'jquery/dist/jquery.slim',
scss: '/home/user/example/projects/example.de/vendor/shopware/storefront/Resources/app/storefront/src/scss',
vendor: '/home/user/example/projects/example.de/vendor/shopware/storefront/Resources/app/storefront/vendor'
}
And those again to not really allow locating the module.
If it is a third-party plugin, replace the path with an absolute path like the following
import ThirdPartyPlugin from '/app/custom/plugins/ThirdPartyPlugin/src/Resources/app/storefront/src/third-party-plugin/third-party-plugin.plugin';

Problems to import json with VueJs

So, I'm trying to import a json file to be able to set some params in my application. The code I'm using to import my json is:
import json from './json/config.json'
export default {
data() {
return {
URL_FILE_IMPORT: json.fileImport,
}
}
}
... and my config.json is very simple so far:
{
"fileImport": "<my_url_goes_here>",
}
The problem is that I'm facing this error:
ERROR Failed to compile with 1 errors
This relative module was not found:
* ./json/config.json in ./src/services/config.js
But I have access to the file, if I click in the ./json/config.json path.
I've seen that there are some differences between some vue.js versions about the json configuration. I'm not 100% sure how to see the version I'm using, but my #vue/cli-service is version 4.2.2. Does anyone knows how to solve it?
So, I've found my solution. It was very simple, I just needed to use
const jsonData = require('../json/config.json');
... and with this I can access jsonData.fileImport
Маке sure the path is correct, if you make import in file ./src/services/config.js with path "./json/data.json" it will look for json in ./src/services/json. Where exactly is your folder /json, if it is in src folder then import should be "../json/data.json". Usually there is alias in web-pack "#" which is to "/src", then import will be "#/json/config.json"

Webpack dynamic import .json file?

I'm using React Intl for x number of languages (example below) and at the moment Im importing the following where I setup my App:
import { addLocaleData } from 'react-intl';
import locale_en from 'react-intl/locale-data/en';
import locale_de from 'react-intl/locale-data/de';
import messages_en from './translations/en.json';
import messages_de from './translations/de.json';
addLocaleData([...locale_en, ...locale_de]);
...
export const messages = {
en: messages_en,
de: messages_de
}
Since these language files are being imported no matter which language is being used my main bundle js file is getting pretty big, especially from the .json files.
How can I with Webpack split these language files (or copy them to my dist folder using CopyWebpackPlugin) and then dynamically import them based on the language being used at the moment?
The app is isomorphic so this same code is being run on the server.
I've been working on something like this lately, although I don't need SSR for my project. I found that pairing dynamic import syntax with React's Suspense component achieves the desired result. Here's a rough overview of what I found to work, at least in my case, which doesn't include SSR:
// wrap this around your JSX in App.js:
<React.Suspense fallback={<SomeLoadingComponent />}>
<AsyncIntlProvider>
{/* app child components go here */}
</AsyncIntlProvider>
</React.Suspense>
// the rest is in support of this
// can be placed in another file
// simply import AsyncIntlProvider in App.js
const messagesCache = {};
const AsyncIntlProvider = ({ children }) => {
// replace with your app's locale getting logic
// if based on a hook like useState, should kick off re-render and load new message bundle when locale changes (but I haven't tested this yet)
const locale = getLocale();
const messages = getMessages(locale);
return (
<IntlProvider locale={locale} messages={messages}>
{children}
</IntlProvider>
);
};
function getMessages(locale) {
if (messagesCache[locale]) {
return messagesCache[locale];
}
// Suspense is based on ErrorBoundary
// throwing a promise will cause <SomeLoadingComponent /> to render until the promise resolves
throw loadMessages(locale);
}
async function loadMessages(locale) {
// dynamic import syntax tells webpack to split this module into its own chunk
const messages = await import('./path/to/${locale}.json`);
messagesCache[locale] = messages;
return messages;
}
Webpack should split each locale JSON file into its own chunk. If it doesn't, something is likely transpiling the dynamic import syntax to a different module system (require, etc) before it reaches webpack. For example: if using Typescript, tsconfig needs "module": "esnext" to preserve import() syntax. If using Babel, it may try to do module transpilation too.
The chunk output for a single locale will look something like this; definitely more than would be achieved via CopyWebpackPlugin:
(window["webpackJsonp"] = window["webpackJsonp"] || []).push([[0],{
/***/ "./path/to/en-US.json":
/*!*************************************!*\
!*** ./path/to/en-US.json ***!
\*************************************/
/*! exports provided: message.id, default */
/***/ (function(module) {
eval("module.exports = JSON.parse(\"{\\\"message.id\\\":\\\"Localized message text\\\"}\");//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiLi9zcmMvbG9jYWxpemF0aW9uL2VuLVVTLmpzb24uanMiLCJzb3VyY2VzIjpbXSwibWFwcGluZ3MiOiIiLCJzb3VyY2VSb290IjoiIn0=\n//# sourceURL=webpack-internal:///./path/to/en-US.json\n");
/***/ })
}]);
Hopefully, this is a good starting point and either works with SSR or can be modified to work with SSR. Please report back with your findings on that subject. 🙂

Next.js with FortAwesome and SSR

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.

Javascript JSX, illegal import declaration

I have a jsx file using React components with Reflux. There is only one tiny action:
var ClickedAction = Reflux.createActions([
'clicked'
]);
How can I move this action to another file? According to the JSX documentation, it should be easy to include other files:
// import all classes that do not start with "_" from "a.jsx"
import "a.jsx";
I tried to move it in actions/clickedAction.jsx (or .js) and import it using import "actions/clickedActions.jsx" but I keep getting Illegal import declaration. How can I achieve this?
I am not using RequireJS and would like to avoid it if possible. One alternative solution I have found is to include this in the HTML file,
<script type='text/javascript' src='xxxxx/actions/clickedAction.js")'></script>
, but this is not ideal and would like to find another way. Thanks for your attention and help.
If you use Babel:
export default ClickedAction; // in action file
Otherwise, use old modules:
module.exports = ClickedAction; // in action file
require('actions/clickedActions.jsx'); // in another file

Categories

Resources