Categories
Uncategorised

Next.js

A react framework can do static and server-side rendering. Automatic code split feature compile and export into chunks by each page entry points. So pages only loads the required code in order to improve the application’s initial load. Also prefetch is a nice feature happens in the background. Any <Link /> that is in the viewport (initially or through scroll) will be preloaded.

Data Fetching

It supports CSR, SSR, SSG and ISR(Incremental Static Regeneration).

We should use getStaticProps and getStaticPaths, if:

  • Get required data needs to be available at build time, is ahead of user’s request.
  • Good example: Data coming from headless CMS.
  • Pages must be pre-rerendered (for SEO) and be very fast. Because it generates HTML and JSON files which can be cached by CDN for better performance.
  • Non user-specifc data want to be cached.
export const Post = ({ post }) => {
  const router = useRouter()

  if (router.isFallback) {
    return <div>Loading...</div>
  }

  return (
    <>
      <h2>
        {post.id} {post.title}
      </h2>
      <p>{post.body}</p>
    </>
  )
}

export async function getStaticProps(context) {
  const { params } = context
  const response = await fetch(
    `https://jsonplaceholder.typicode.com/posts/${params.postId}`
  )
  const data = await response.json()

  if (!data.id) {
    return {
      notFound: true
    }
  }

  console.log(`Generating page for /posts/${params.postId}`)
  return {
    props: {
      post: data
    }
  }
}

export async function getStaticPaths() {
    const response = await fetch('https://jsonplaceholder.typicode.com/posts')
    const data = await response.json()
    const paths = data.map(post => {
      return {
        params: { postId: `${post.id}` }
      }
  })
  return {
    paths: [
      { params: { postId: '1' } },
      { params: { postId: '2' } },
      { params: { postId: '3' } }
    ],
    fallback: true
  }
}

getStaticProps

Next.js will pre-render this page at build time using the props returned by getStaticProps.

getStaticPaths

When you export a function called getStaticPaths (Static Site Generation) from a page that uses dynamic routes, Next.js will statically pre-render all the paths specified by getStaticPaths.

getServerSideProps

When getServerSideProps exports as a standalone function, we can fetch those data must be fetched at request time (such as authorization or geo location). It runs only on the server-side and these data only be cached if “cache-control” headers are configured.

You can consider it’s a way to grab

Build-in CSS support

It allows you to import the CSS from a javascript file without extra configuration. The CSS from “node_modules” can simply import like below.

// pages/_app.js
import 'bootstrap/dist/css/bootstrap.css'

export default function MyApp({ Component, pageProps }) {
  return <Component {...pageProps} />
}

CSS modules, sass, and less are also supported.

Image component and Image optimization

It offered a next/image component, is a expansion of the HTML <img> element. The image optimization can do resizing and serving the modern image format webp. It avoids transfer huge pictures with a smaller viewport. With the default “intrinsic” layout, images will scale the dimensions down for smaller viewports, but remain the original demensions for larger viewports. The optimization works with any picture rouce, no matter it’s from local or external.

  • Improve performance: images can be resized and encoded on demand, or even it’s from external. It avoids unnecessary steps for creating different sizes of images.
  • Responsiveness: images can be resized based on the screen size.
  • Visual stability: the cumulative layout shift problem is automatically avoided. It’s a layout shift common issue.
  • Faster page load: Next.js images will only be loaded when entering the viewport, being lazy-loaded by default.
  • Better Google search rankings.

Middleware

Next.js Middleware allows you to run the code before a request is completed, then based on the incoming request, you can modify the response by rewriting, redirecting, adding headers, or setting cookies.

Cick for more stuff about how to use it.

Categories
Frontend

React 18 thoughts

// Before
import { render } from 'react-dom';
const container = document.getElementById('app');
render(<App tab="home" />, container);
// After
import { createRoot } from ‘react-dom/client’;
const container = document.getElementById(‘app’);
const root = createRoot(container);
root.render(<App tab=”home” />);

Concurrency, is the main feature.

The main reason that it’s using “createRoot”, is because the new behind-the-scenes mechanism that enable React to prepare multiple version of the UI components at the same time, which is CONCURRENCY. Prior to React 18, updates were handled with synchronous rendering, thus with single, uninterrupted transactions. NOW rendering is interruptible. The key is that react is now basically preparing the components without blocking any user input or app flow.

For example:

Autocomplete is always a good example. In React 18, we can ask the component to be managed in the background. While the transaction is pending, the user still is able to type without a laggy experience.

I knew in React 17 we can do debounce and throttle, the examples below are just for comparation.

Source: Examples for React 18 Concurrency

Automatic Batching

Automatic Batching or default grouping multiple state updates (versus previous versions which only grouped updates inside event handlers) into a single re-render. Before React 18, it’s only do batch state updates when it’s in the scenarios browser-like “click event”. If it’s wrapped in a call back and it won’t do “batch state updates”. NOW React 18 will batch updates automatically, no matter where the updates happen.

Source: Automatic Batching.

Transitions 

It allows for a new way to differentiate between updates. Just like the autocomplete example above, we ensure the UI updates will not block user typing behavior.

Official React: Transition Docs

Suspense

Suspense Features for declaring the loading state of the component tree, which work well when combined with a transition API.

A perfect example from YouTube below:

More Info: Suspense in React 18

New Client and Server Rendering APIs

It’s related to the new method createRoot to render (and unmount), but read more on React DOM Client and React DOM Server

New Strict mode: useEffect is Double Called

Other Stuffs

Categories
Backend

ORM thoughts?

People might have confusion when we start to think about traditional ORM like sequelize.

Got the explanation “Sequelize vs Prisma” from Prisma

While Prisma and Sequelize solve similar problems, they work in very different ways.

Sequelize is a traditional ORM which maps tables to model classes. Instances of the model classes then provide an interface for CRUD queries to an application at runtime.

Prisma is a new kind of ORM that mitigates many problems of traditional ORMs, such as bloated model instances, mixing business with storage logic, lack of type-safety or unpredictable queries caused e.g. by lazy loading.

It uses the Prisma schema to define application models in a declarative way. Prisma Migrate then allows to generate SQL migrations from the Prisma schema and executes them against the database. CRUD queries are provided by Prisma Client, a lightweight and entirely type-safe database client for Node.js and TypeScript.

Battle of the Node.js ORMs: Objection vs. Prisma vs. Sequelize

The first impression of Objection.js is more like a query builder instead of a common ORM. The way of defining models and relationships can be nicely achieved with custom methods, json and schema validation. We can also do Database transactions easily with promise.

const people = await Person.query()
  .select('parent:parent.name as grandParentName')
  .joinRelated('parent.parent');

console.log(people[0].grandParentName);
select "parent:parent"."firstName" as "grandParentName"
from "persons"
inner join "persons"
  as "parent"
  on "parent"."id" = "persons"."parentId"
inner join "persons"
  as "parent:parent"
  on "parent:parent"."id" = "parent"."parentId"

The eager loading is quite interesting too. “withGraphFetched and withGraphJoined. The main difference is that withGraphFetched uses multiple queries under the hood to fetch the result while withGraphJoined uses a single query and joins to fetch the results. Both methods allow you to do different things which we will go through in detail in the examples below and in the examples of the withGraphJoined method.”

Categories
Uncategorised

Git Configurations

Pull with Rebase

Git push with rebase instead of “merge”.

git config --global pull.rebase true

Push only to the current branch.

If its named upstream is identical

git config –global push.default simple

Categories
Drupal

Drupal theme

Create the theme

1. Create a theme file in:
yourProject/themes/your_theme_name/theme_name.info.yml
2. Add content to your theme file:
name: Beautiful theme
type: theme
base theme: classy
description: 'A great theme for warm summer days.'
package: Custom
core: 8.x
Extra: Key/value pairs in theme_name.info.yml
name (required)
type (required)
description (optional)
package (optional)
core (required)
php (optional)
version (optional)
libraries (optional)
libraries-override (optional)
libraries-extend (optional)
base theme (recommended)
hidden (optional)
engine (optional)
logo (optional)
screenshot (optional)
regions (optional)
regions_hidden (optional)
features (optional)
stylesheets-remove (deprecated)
ckeditor_stylesheets (optional)
Tips:
  • Theme naming: name_with_underscore is required by drupal.
  • Tabs are NOT allowed. Use spaces ONLY.
  • Properties and lists MUST be indented by two (2) spaces.
  • https://www.drupal.org/node/2349827
  • drush cr is required after the changes, is clean all the cache.
  • https://drupalize.me/tutorial/create-info-file-module?p=2766

Structrue of Drupal Project

Drupal root 
+-- core
|   +-- themes
|       +-- bartik
|       +-- classy
|       +-- engines
|       +-- seven
|       +-- stable
|       +-- stark
+-- sites
|   +-- *
|       +-- themes
|           +-- maya
+-- themes
    +-- contrib
        +-- zen        
    +-- custom
        +-- my_custom_theme

Structrue of Theme

Theme root 
+-- assets
+-- src
+-- templates
|   +-- block
|   +-- content
|   +-- field
|   +-- form
|   +-- icons
|   +-- layout
|   |     -- html.html.twig
|   +-- ...and more
theme_name.info.yml
theme_name.libraries.yml
theme_name.breakpoints.yml
theme_name.theme
  • theme_name.info.yml is required.
  • theme_name.theme is a PHP file that contains conditional logic, and handles preprocessing of variables before they are output via template files.
  • templates/*.html.twig is used to override the base twig template files.
  • theme_name.libraries.yml define CSS and JavaScript libraries that can be loaded by your theme. All CSS and JavaScript should be added to the page via an asset library.