What is the right way to incude Sass in NextJs? - reactjs

When I use Sass files in NextJs, I am getting 'conflicting order' warnigs from mini-css-extract-plugin. The conflict always messes up my stylings on build. You can see the error described in the following link:
https://medium.com/iryl/control-css-imports-order-for-next-js-webpack-based-production-applications-3b69765444fd
This is an article with a solution to this issue but it talks about ordering Sass files for only one page. I'm not sure how to do order when there are multiple pages. How can I tackle the conflicting order issue?

if you are using nextjs 9.3 or higher you can use it like css modules. At least this is how they recommend that you do it.
This is an example.
You can also check the Sass support on the Next.js docs.
-- Update
The best way of do it it's by creating a different scss module for each component. It will look something like this.
Components
├── Header
│ ├── Header.js
│ ├── Header.module.css
├── Footer
│ ├── Footer.js
│ ├── Footer.module.css
├── Nav
│ ├── Nav.js
│ ├── Nav.module.css
The main idea of using css modules it's to prevent you from use a global sheet. this way the css will be optimized on the code splitting by components and you don't have to worry about declaring the same class twice, each css module file will generate a unique class name.
I'm working on a project using css modules, the project isn't done yet but the file structure it's almost the same working with sass, you can give it a look if you want.
https://github.com/edgarlr/portfolio/tree/main/components

Related

Disable Specific Paths for Next.JS File System Routing [duplicate]

There are SSR-related problems with several pages in Next.js project that results in errors on npm run build and prevent the project from being built:
pages/
foo/
bar/
[id].jsx
index.jsx
index.jsx
...
For example, bar:
export function getStaticProps() {
return someApiCallThatCurrentlyFails()
...
}
export default function Bar() {...}
As a quick fix, it may be convenient to just not build bar/*.* pages and make routes unavailable.
Can pages be ignored on Next.js build without physically changing or removing page component files in the project?
You can configure the pageExtensions in the next.config.js.
// next.config.js
module.exports = {
pageExtensions: ["page.js"],
}
After configuring this, the only pages with *.page.js will be considered in the below given directory structure.
pages/
├── user
│ └── setting
│ ├── index.js
├── _app.page.js
├── _document.page.js
├── list.page.js
└── theme.ts
Custom file ignores patterns that are not supported yet. You can visit the PR created here, and the solution given here. This is the most satisfactory solution so far.
#Mathilda Here from Nextjs docs: it's necessary for all pages including _app, _document, etc.
https://nextjs.org/docs/api-reference/next.config.js/custom-page-extensions
Changing these values affects all Next.js pages, including the following:
- middleware.js
- pages/_document.js
- pages/_app.js
- pages/api/
For example, if you reconfigure .ts page extensions to .page.ts, you would need to rename pages like _app.page.ts.

How to set up a chrome extension using React and TypeScript with multiple pages and entry points?

There are plenty of questions and tutorials on this topic, but none of them cover all use cases for a chrome extension, because most of them assume there's only one entry point.
Here are the requisites:
Multiple "single page applications":
1) popup.html for the extension pop up page
2) options.html for the options page
3) custom.html this is a custom .html file that the extension can refer to "locally"
Each of these files are entry points for React to manipulate the DOM, but they behave independently of each other.
Non React TypeScript files
They must not be bundled together with any other scripts, and gets compiled to its own JavaScript file, for example a background.ts that compiles to background.js (which is refered to in the manifest.json).
I assume this is doable with TypeScript, React and Webpack but I'm not sure how to approach that.
There is a custom CRA template that exactly fits your needs: complex-browserext-typescript.
Usage:
npx create-react-app my-app --template complex-browserext-typescript
By default it sets up 4 entry points associated with page-like extension components:
popup (src/index.tsx) - extension's popup page, replaces the
default index entry point.
options (src/options.tsx) - extension's options page.
background (src/background.ts) - background script.
content (src/content.ts) - content script.
However there is an option to exclude any of the above components except the popup from compilation as well as add extra HTML page(s).
Also see this article for usage example.
I found a solution but it was not using create-react-app and webpack. It looks like parcel supports multiple entry points out of the box without any configuration.
Assuming a directory structure like this:
├── chrome
│   └── background.ts
├── html
│   ├── custom.html
│   ├── options.html
│   └── popup.html
├── manifest.json
├── package.json
├── react
│   ├── custom.tsx
│   ├── options.tsx
│   └── popup.tsx
With Parcel.js you simply do:
parcel build html/*.html react/*.tsx chrome/*.ts
And it will handle the multiple entry points. I created a repository that contains a template for that approach, it contains a fully runnable example.

How can I use ComponentName.js instead of index.js when importing React component (from Atomic design structure directory)

I am using Gatsby (React) for my project. I am using Atomic design folder structure e.g:
src/components/Organisms/Header
In this folder I like to have:
src/components/Organisms/Header/header.js
src/components/Organisms/Header/header.module.scss
How can I import header.js from within src/components/layout.js like:
import Header from '#components/Organisms/Header'
instead of:
import Header from '#components/Organisms/Header/header'
Update:
I managed to do it by:
adding an index.js file to src/components/Organisms/Header/
and export { default } from './header'; in index.js
But are this best practices?
You have a few options here. With all of these you would import src/components/Header.
1. Flat with no component directory (my preference):
src
└── components
├── Header.js
└── header.module.css
Benefits
Less meaningless nesting
No conflicting/confusing filenames open in your editor (e.g. index)
Easy to follow the imports and exports
Drawbacks
Nowhere for one-off resources and sub-components to go
2. Adjacent component and resources-directory (Ruby-style):
src
└── components
├── Header
│   ├── header.module.css
│   └── logo.png
└── Header.js
Benefits
Resources and sub-components are kept together
No conflicting/confusing filenames open in your editor (e.g. index)
Easy to follow the imports and exports
Drawbacks
The component isn't adjacent to resources, so imports require a ./Header/ prefix
Depending on the sorting, the resources directory may not be listed immediately adjacent to the component
3. With a directory index that exports Header:
src
└── components
└── Header
├── Header.js
├── header.module.css
├── index.js
└── logo.png
Benefits
Component and resources are kept together
Sorting doesn't matter
Drawbacks
Conflicting/confusing filenames open in your editor (e.g. index)
Confusing imports and exports, may cause hard-to-diagnose errors
Extra work for every component

How to create multiple static pages with Hugo?

I'm trying to build a basic landing page on GitHub pages using Hugo (version 0.44) and the hugo-sustain theme. But I struggle to understand how to organise content with Hugo.
This is the basic example site from the hugo-sustain theme:
exampleSite
├── config.toml
├── content
│ ├── projects.md
│ └── blog
│ ├── creating-a-new-theme.md
│ ├── go-is-for-lovers.md
│ ├── hugo-is-for-lovers.md
│ └── migrate-from-jekyll.md
├── data
│ └── projects.yml
└── static
Now I'd like a nice projects page, where I have images and/or text.
But with the hugo-sustain theme the actual text content and the project's descriptions are in the projects.yml file. But not in the projects.md as I'd have expected.
That means it will be a lot harder to encode content that will nicely compile as a static page.
I have found this workaround with getting static pages set up following this post. But is that really the best-practice approach? It feels quite messy and involved for just one simple page.
Now I'd like a nice projects page, where I have images and/or text.
Generating pages from data in Hugo is currently not possible and will (most likely) not become possible in the near future: https://github.com/gohugoio/hugo/issues/5074
That means you have to create a section projects with .md files of each project. They will have their own layouts. The alternative is to use the trick from Regis (https://www.thenewdynamic.com/) where you run Hugo twice: once to transform data into .md files and once to render the .md files.

Webpack code splitting to asynrounously load react components within a library

We have developed a React component library for internal use. The library uses webpack to bundle everything into a bundle.js. The library is exposed as an NPM module for use by our applications, which so far has been working great.
Recently we added a Grid component that has some very large external dependencies. Even though a few of our applications won't need this component from the library, we decided to include it in the final bundle. This can make a huge difference in bundle size, so I followed Webpack's code splitting guide to break out the Grid component using a dynamic import. For our applications that have this library installed as an NPM module, the component library bundle now looks like this in node_modules:
├── node_modules/
│ ├── [our component library]/
│ │ ├── Grid.js # Asynchronously loaded Grid component
│ │ ├── bundle.js # Main bundle
│ │ └── ... other files in component library bundle
When building the application (also with Webpack), the Grid component doesn't seem to be getting included as its own file in the final bundle. In fact, it doesn't get included at all:
├── dist/
│ ├── main.js # App bundle
│ ├── vendor.js # Vendor bundle created with CommonChunksPlugin
│ └── ... other files in application bundle but no Grid.js
When trying to load a page in the browser that is using the asynchronously loaded Grid component, Webpack returns the following error:
Error: Loading chunk 0 failed.
at HTMLScriptElement.onScriptComplete (bundle.js:757)
Essentially, this says the Grid component chunk can't be found. What am I doing wrong? Is it even possible to code split a React component library like this?
I used https://webpack.js.org/guides/code-splitting/#dynamic-imports both import() and require.ensure syntax for dynamic imports. Both worked well. Check this project of mine for good example https://github.com/croraf/myboiler.
This project also is an example: https://github.com/croraf/nutrients-calculator. But I complicated dynamic import part a bit. Check https://github.com/croraf/nutrients-calculator/blob/master/frontend/src/App.js and https://github.com/croraf/nutrients-calculator/blob/master/frontend/src/routes/util/DynamicRoute.js files.
We decided to take a different route with this. Instead of including the Grid component with the rest of the components we split if off into its own npm module. I still see a use case for dynamically importing react components in a library but we felt this was a better solution to our problem. With this solution, the only real downside is that the application will now need to add 2 npm modules instead of one if it needs to use the Grid component and our standard component library. Since our application does code splitting by route with webpack + dynamic imports, the Grid code only gets bundled into the route that needs it.
one possible reason is babel transpiled your code from import("..") to require. check transpiled file to confirm this.
if this is the case and you are using preset, you can add this to disable this behavior:
"#babel/preset-env",
{
**"modules": false,**
"targets": {
"esmodules": true
}
}
],

Resources