Skip to content

This example shows how to do a optimized mobile website and a responsive desktop website on NextJS

Notifications You must be signed in to change notification settings

ganobrega/nextjs-mobile-first

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

9 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

NextJS Mobile First (Experimental)

This example shows how to do a optimized website for mobile and a responsive website for desktop in the same stack.

>> Check the demo << and use Lighthouse to check the performance!

Lighthouse Report

Desktop Responsive Website

Optimized Mobile Website

Requirements

Setup

server.js

+ const device = require('device');

app.prepare().then(() => {
   createServer((req, res) => {
+     const _device = device(req.headers['user-agent']);
+     req.device = _device.type;

      handle(req, res, parsedUrl)
   }).listen(3000, (err) => {
      if (err) throw err
      console.log('> Ready on https://localhost:3000')
   })
})

_document.js

with styled-components SSR

import Document from 'next/document';
import { ServerStyleSheet } from 'styled-components';
+import { mediaStyles } from '../components/media';

export default class MyDocument extends Document {
  static async getInitialProps(ctx) {
    const sheet = new ServerStyleSheet();
    const originalRenderPage = ctx.renderPage;

    try {
      ctx.renderPage = () =>
        originalRenderPage({
          enhanceApp: (App) => (props) =>
            sheet.collectStyles(<App {...props} />),
        });

      const initialProps = await Document.getInitialProps(ctx);
      return {
        ...initialProps,
        styles: (
          <>
+            {ctx.req.device === 'desktop' && (
+             <style type="text/css" dangerouslySetInnerHTML={{ __html: mediaStyles }} />
+            )}
            {initialProps.styles}
            {sheet.getStyleElement()}
          </>
        ),
      };
    } finally {
      sheet.seal();
    }
  }
}

_app.js

import App from 'next/app';
import { ThemeProvider } from 'styled-components';
+import { Context as MediaContext, MediaContextProvider, } from '../components/media';


export default class MyApp extends App {
+  static async getInitialProps(ctx) {
+    const appProps = await App.getInitialProps(ctx);
+
+    const device = ctx.ctx.req.device;
+
+    return { ...appProps, device };
+  }

  render() {
    const { Component, pageProps, device } = this.props;

    return (
+      <MediaContext.Provider value={device}>
+        {device === 'desktop' ? (
+          <MediaContextProvider>
+            <ThemeProvider theme={theme}>
+              <Component {...pageProps} />
+            </ThemeProvider>
+          </MediaContextProvider>
+        ) : (
+          <ThemeProvider theme={theme}>
+            <Component {...pageProps} />
+          </ThemeProvider>
+        )}
+      </MediaContext.Provider>
    );
  }
}

components/media.js

import React, { useContext } from 'react';
import { createMedia } from '@artsy/fresnel';

export const Context = React.createContext();

/**
 * Components
 */
export const Mobile = ({ children }) => {
  const context = useContext(Context);

  return context === 'phone' ? (
    children
  ) : (
    <Media lessThan="lg">{children}</Media>
  );
};

export const Desktop = ({ children }) => {
  const context = useContext(Context);

  return context === 'desktop' ? (
    <Media greaterThan="md">{children}</Media>
  ) : null;
};

export const NotDesktop = ({ children }) => {
  const context = useContext(Context);

  if (context === 'phone') {
    return children;
  }

  return context !== 'desktop' ? (
    children
  ) : (
    <Media lessThan="lg">{children}</Media>
  );
};

const Medias = createMedia({
  breakpoints: {
    xs: 0,
    sm: 576,
    md: 768,
    lg: 1024,
    xl: 1200,
  },
});

export const mediaStyles = Medias.createMediaStyle();

export const { Media, MediaContextProvider } = Medias;

About

This example shows how to do a optimized mobile website and a responsive desktop website on NextJS

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published