### Installing Dependencies and Starting Application (bash) Source: https://github.com/lomray-software/after.js/blob/master/examples/with-scss/README.md This snippet installs the project dependencies using yarn and then starts the application, likely a development server, using the yarn start command. ```bash yarn install yarn start ``` -------------------------------- ### Install Dependencies and Start Development Server (Bash) Source: https://github.com/lomray-software/after.js/blob/master/examples/with-static-export/README.md Installs the project dependencies using yarn and starts the development server for the example application. ```bash yarn install yarn start ``` -------------------------------- ### Quickstart with create-after-app and Razzle (Bash) Source: https://github.com/lomray-software/after.js/blob/master/packages/after.js/README.md Provides commands to quickly set up and start a new After.js application using the `create-after-app` CLI tool and the Razzle build tool. It covers global installation, project creation, changing directory, and starting the development server. ```Bash yarn global add create-after-app create-after-app myapp cd myapp yarn start ``` -------------------------------- ### Install Dependencies and Start Razzle/After.js Example (Bash) Source: https://github.com/lomray-software/after.js/blob/master/examples/basic/README.md Assuming you are in the example directory, this snippet first installs all project dependencies listed in the package.json file using yarn, and then starts the development server for the Razzle/After.js application. ```bash yarn install yarn start ``` -------------------------------- ### Install Dependencies and Start Project - Bash Source: https://github.com/lomray-software/after.js/blob/master/examples/with-context-api/README.md Installs the project dependencies using yarn and then starts the development server. ```bash yarn install yarn start ``` -------------------------------- ### Install Dependencies and Start Project (bash) Source: https://github.com/lomray-software/after.js/blob/master/packages/create-after-app/templates/default/README.md These commands are executed within the example project directory. 'yarn install' fetches and installs all necessary project dependencies, and 'yarn start' runs the development server to launch the application. ```bash yarn install yarn start ``` -------------------------------- ### Downloading and Navigating to Example Directory (bash) Source: https://github.com/lomray-software/after.js/blob/master/examples/with-scss/README.md This snippet downloads the basic example from the after.js GitHub repository using curl, extracts it while stripping directory levels, and then changes the current directory to the extracted example folder. ```bash curl https://codeload.github.com/jaredpalmer/after.js/tar.gz/master | tar -xz --strip=2 razzle-master/examples/basic cd basic ``` -------------------------------- ### Install Dependencies and Run Example (Bash) Source: https://github.com/lomray-software/after.js/blob/master/examples/with-material-ui/README.md Installs project dependencies using yarn and then starts the development server for the Material UI example. ```bash yarn install yarn start ``` -------------------------------- ### Quickstart with create-after-app Source: https://github.com/lomray-software/after.js/blob/master/README.md This snippet provides the commands to quickly set up a new After.js project using the create-after-app CLI tool. It demonstrates adding the tool globally, creating a new app directory, navigating into it, and starting the development server. ```bash yarn global add create-after-app create-after-app myapp cd myapp yarn start ``` -------------------------------- ### Install and Run After.js Layout Example Source: https://github.com/lomray-software/after.js/blob/master/examples/layout-component/README.md Install project dependencies and start the development server for the layout component example using yarn. ```bash yarn install yarn start ``` -------------------------------- ### Install Dependencies and Run After.js Material UI RTL Example (Bash) Source: https://github.com/lomray-software/after.js/blob/master/examples/with-material-ui-rtl/README.md Install the necessary project dependencies using Yarn and then start the development server. These commands are executed within the example project directory after it has been set up or downloaded. ```bash yarn install yarn start ``` -------------------------------- ### Create New App with Example and Start (Bash) Source: https://github.com/lomray-software/after.js/blob/master/examples/with-static-export/README.md Uses the yarn create command to scaffold a new project based on the 'with-static-export' example, navigates into the new directory, and starts the development server. ```bash yarn create after-app --example with-static-export after-with-static-export cd after-with-static-export yarn start ``` -------------------------------- ### Create After.js App from Example with npx Source: https://github.com/lomray-software/after.js/blob/master/packages/create-after-app/README.md Use npx to initialize an After.js project based on a specific example (e.g., 'with-preact'), navigate into the project directory, and start the development server. ```bash npx create-after-app --example with-preact my-preact-app cd my-preact-app npm start ``` -------------------------------- ### Download and Navigate to Example Directory - Bash Source: https://github.com/lomray-software/after.js/blob/master/examples/with-context-api/README.md Downloads the basic example from the after.js repository using curl and extracts it, then changes the current directory to the example's root. ```bash curl https://codeload.github.com/jaredpalmer/after.js/tar.gz/master | tar -xz --strip=2 razzle-master/examples/basic cd basic ``` -------------------------------- ### Download and Navigate to Example Directory (Bash) Source: https://github.com/lomray-software/after.js/blob/master/examples/with-static-export/README.md Downloads the 'with-static-export' example from the after.js repository using curl and tar, then changes the current directory into the extracted example folder. ```bash curl https://codeload.github.com/jaredpalmer/after.js/tar.gz/master | tar -xz --strip=2 after.js-master/examples/with-static-export cd with-static-export ``` -------------------------------- ### Download and Extract After.js Example (bash) Source: https://github.com/lomray-software/after.js/blob/master/packages/create-after-app/templates/default/README.md This command sequence downloads a specific example directory ('basic') from the After.js GitHub repository using curl, extracts it, and then changes the current directory to the extracted 'basic' folder. ```bash curl https://codeload.github.com/jaredpalmer/after.js/tar.gz/master | tar -xz --strip=2 razzle-master/examples/basic cd basic ``` -------------------------------- ### Create After.js App from Example with yarn create Source: https://github.com/lomray-software/after.js/blob/master/packages/create-after-app/README.md Use yarn create to initialize an After.js project based on a specific example (e.g., 'with-preact') and navigate into the project directory. ```bash yarn create after-app --example with-preact my-preact-app cd my-preact-app ``` -------------------------------- ### Bootstrap After.js Layout Example (npx) Source: https://github.com/lomray-software/after.js/blob/master/examples/layout-component/README.md Use the create-after-app tool with npx to quickly set up the layout component example project. ```bash npx create-after-app --example layout-component layout-component-app ``` -------------------------------- ### Build the Application (Bash) Source: https://github.com/lomray-software/after.js/blob/master/examples/with-static-export/README.md Runs the Razzle build command to compile the application for production deployment. ```bash yarn build ``` -------------------------------- ### Download After.js Material UI RTL Example Manually (Bash) Source: https://github.com/lomray-software/after.js/blob/master/examples/with-material-ui-rtl/README.md Download the After.js project archive, extract the specific Material UI RTL example directory, and navigate into it. This method is an alternative to using create-after-app for obtaining the example code. ```bash curl https://codeload.github.com/jaredpalmer/after.js/tar.gz/master | tar -xz --strip=2 after.js-master/examples/with-material-ui-rtl cd with-material-ui-rtl ``` -------------------------------- ### Bootstrap After.js App with Material UI RTL (Bash) Source: https://github.com/lomray-software/after.js/blob/master/examples/with-material-ui-rtl/README.md Use the create-after-app command-line tool to quickly generate a new After.js project pre-configured with the Material UI RTL example. This command fetches the specified example and sets up a new project directory. ```bash npx create-after-app --example with-material-ui-rtl with-material-ui-rtl-app ``` -------------------------------- ### Download Material UI Example Manually (Bash) Source: https://github.com/lomray-software/after.js/blob/master/examples/with-material-ui/README.md Downloads and extracts the specific Material UI example directory from the After.js repository using curl and tar, then navigates into the extracted directory. ```bash curl https://codeload.github.com/jaredpalmer/after.js/tar.gz/master | tar -xz --strip=2 after.js-master/examples/with-material-ui cd with-material-ui ``` -------------------------------- ### Bootstrap After.js App with Material UI (Bash) Source: https://github.com/lomray-software/after.js/blob/master/examples/with-material-ui/README.md Uses the `create-after-app` command-line tool to quickly set up a new After.js project pre-configured with the Material UI example. ```bash npx create-after-app --example with-material-ui with-material-ui-app ``` -------------------------------- ### Installing babel-plugin-after (Yarn) Source: https://github.com/lomray-software/after.js/blob/master/packages/babel-plugin-after/README.md Command to install the babel-plugin-after package using Yarn as a development dependency. ```shell $ yarn add -D babel-plugin-after ``` -------------------------------- ### Installing babel-plugin-after (npm) Source: https://github.com/lomray-software/after.js/blob/master/packages/babel-plugin-after/README.md Command to install the babel-plugin-after package using npm as a development dependency. ```shell $ npm install babel-plugin-after --save-dev ``` -------------------------------- ### Download and Extract After.js Basic Example (Bash) Source: https://github.com/lomray-software/after.js/blob/master/examples/basic/README.md This snippet uses curl to download the After.js master branch archive, pipes it to tar to extract the 'razzle-master/examples/basic' directory while stripping parent directories, and then changes the current directory to the extracted 'basic' folder. ```bash curl https://codeload.github.com/jaredpalmer/after.js/tar.gz/master | tar -xz --strip=2 razzle-master/examples/basic cd basic ``` -------------------------------- ### Download After.js Layout Example (curl) Source: https://github.com/lomray-software/after.js/blob/master/examples/layout-component/README.md Manually download and extract the layout component example from the After.js repository using curl and tar. ```bash curl https://codeload.github.com/jaredpalmer/after.js/tar.gz/master | tar -xz --strip=2 after.js-master/examples/layout-component cd layout-component ``` -------------------------------- ### Create Basic After.js App with npx Source: https://github.com/lomray-software/after.js/blob/master/packages/create-after-app/README.md Use npx to initialize a new After.js project with default settings, navigate into the project directory, and start the development server. ```bash npx create-after-app my-proj cd my-proj npm start ``` -------------------------------- ### Configuring babel-plugin-after with Options (JSON) Source: https://github.com/lomray-software/after.js/blob/master/packages/babel-plugin-after/README.md Configuration example showing how to pass options, specifically the 'prefix' option, to the plugin within the .babelrc file. ```json { "plugins": ["after", { "prefix": "MyPrefix-" }] } ``` -------------------------------- ### Using babel-plugin-after via CLI (Shell) Source: https://github.com/lomray-software/after.js/blob/master/packages/babel-plugin-after/README.md Command line example demonstrating how to apply the babel-plugin-after when transforming a file using the Babel CLI. ```shell $ babel --plugins after script.js ``` -------------------------------- ### Create Basic After.js App with yarn create Source: https://github.com/lomray-software/after.js/blob/master/packages/create-after-app/README.md Use yarn create to initialize a new After.js project with default settings, navigate into the project directory, and start the development server. ```bash yarn create after-app my-proj cd my-proj yarn start ``` -------------------------------- ### Run Static Export (Bash) Source: https://github.com/lomray-software/after.js/blob/master/examples/with-static-export/README.md Executes the static export command, typically defined in package.json, which utilizes the 'static_export.js' file to generate static HTML files for the specified routes. ```bash yarn export ``` -------------------------------- ### Using babel-plugin-after via Node API (JavaScript) Source: https://github.com/lomray-software/after.js/blob/master/packages/babel-plugin-after/README.md Example showing how to use the babel-plugin-after programmatically with Babel's Node API for code transformation. ```javascript require('babel-core').transform('code', { plugins: ['after'], }); ``` -------------------------------- ### Identifying asyncComponent Imports (JavaScript) Source: https://github.com/lomray-software/after.js/blob/master/packages/babel-plugin-after/README.md Examples showing different ways asyncComponent can be imported from '@jaredpalmer/after' or '@jaredpalmer/after/asyncComponent', illustrating how the plugin determines the local name(s) used for the function. ```javascript // example1.js import { asyncComponent } from '@jaredpalmer/after'; // localname is asyncComponent // example2.js import { asyncComponent as foo } from '@jaredpalmer/after'; // localname is foo // example3.js import asyncComponent from '@jaredpalmer/after/asyncComponent'; // localname is asyncComponent // example4.js import foo from '@jaredpalmer/after/asyncComponent'; // localname is foo // example5.js import { asyncComponent as foo, After } from '@jaredpalmer/after'; // localname is foo // example6.js import { After } from '@jaredpalmer/after'; // there is no `asyncComponent` import so babel plugin skips this file // example7.js import loader from '@jaredpalmer/after/asyncComponent'; // localname is loader import { asyncComponent, After } from '@jaredpalmer/after'; // localname is asyncComponent // localname = [`loader`, `asyncComponent`] :) ``` -------------------------------- ### Define Static Export Functions (JavaScript) Source: https://github.com/lomray-software/after.js/blob/master/examples/with-static-export/README.md Contains the core logic for static export. The 'render' function uses 'renderStatic' from '@jaredpalmer/after' to generate HTML and data for a given route, while the 'routes' function specifies the list of paths to be statically generated. ```javascript // ./src/static_export.js import { renderStatic } from '@jaredpalmer/after'; import appRoutes from './routes'; const assets = require(process.env.RAZZLE_ASSETS_MANIFEST); const chunks = require(process.env.RAZZLE_CHUNKS_MANIFEST); export const render = async (req, res) => { const { html, data } = await renderStatic({ req, res, routes: appRoutes, assets, chunks, }); res.json({ html, data }); }; export const routes = () => { return ['/', '/about']; }; ``` -------------------------------- ### Handling Redirect via getInitialProps in After.js Source: https://github.com/lomray-software/after.js/blob/master/packages/after.js/README.md This example demonstrates how to perform a redirect in After.js by returning `{ redirectTo: '/new-location' }` from `getInitialProps`. This is useful for scenarios like authentication checks where a user needs to be sent to a login page. ```javascript Dashboard.getInitialProps = async ({ match }) => { try { const { data } = await fetchProfile(); return { data }; } catch (error) { if (error.response.status === 401) return { redirectTo: '/login' }; return { error }; } }; ``` -------------------------------- ### Handling Dynamic 404 Manually in Component Source: https://github.com/lomray-software/after.js/blob/master/packages/after.js/README.md This example demonstrates a less ideal approach to handling dynamic 404s. It checks for an error with a 404 status in the component's props and conditionally renders the `Notfound` component or an error message. ```javascript import Notfound from './Notfound'; function ProductPage({ product, error }) { if (error) { if (error.response.status === 404) { return ; } return

Something went Wrong !

; } { /* if there were no errors we have our data */ } return

{product.name}

; } ProductPage.getInitialProps = async ({ match }) => { try { const { data } = await fetchProduct(match.params.slug); return { product: data }; } catch (error) { return { error }; } }; ``` -------------------------------- ### Using Custom Document in After.js Server Setup Source: https://github.com/lomray-software/after.js/blob/master/README.md This snippet shows how to configure an Express server to use the custom Document component with After.js. It imports the custom document and passes it to the `document` option of the `render` function provided by After.js, ensuring the server renders the application using the custom HTML structure. ```javascript // ./src/server.js import express from 'express'; import { render } from '@jaredpalmer/after'; import routes from './routes'; import MyDocument from './Document'; const chunks = require(process.env.RAZZLE_CHUNKS_MANIFEST); const server = express(); server .disable('x-powered-by') .use(express.static(process.env.RAZZLE_PUBLIC_DIR)) .get('/*', async (req, res) => { try { // Pass document in here. const html = await render({ req, res, document: MyDocument, chunks, routes, }); res.send(html); } catch (error) { console.error(error); res.json({ message: error.message, stack: error.stack }); } }); export default server; ``` -------------------------------- ### Handling Dynamic 404s Manually in Component Render Source: https://github.com/lomray-software/after.js/blob/master/README.md This example demonstrates a less ideal approach to handling dynamic 404s. It checks for an error prop within the component's render function and conditionally renders the 'Notfound' component if the error status is 404. This method can make components harder to read and maintain. ```javascript import Notfound from './Notfound'; function ProductPage({ product, error }) { if (error) { if (error.response.status === 404) { return ; } return

Something went Wrong !

; } { /* if there were no errors we have our data */ } return

{product.name}

; } ProductPage.getInitialProps = async ({ match }) => { try { const { data } = await fetchProduct(match.params.slug); return { product: data }; } catch (error) { return { error }; } }; ``` -------------------------------- ### Performing Redirects via getInitialProps in After.js Source: https://github.com/lomray-software/after.js/blob/master/README.md This example demonstrates how to perform server-side redirects in After.js. The 'getInitialProps' function checks for a condition (e.g., 401 unauthorized API response) and returns '{ redirectTo: "/new-location" }'. After.js intercepts this and performs a fast redirect before rendering the component. The default status code for redirects is 301, but can be customized. ```javascript Dashboard.getInitialProps = async ({ match }) => { try { const { data } = await fetchProfile(); return { data }; } catch (error) { if (error.response.status === 401) return { redirectTo: '/login' }; return { error }; } }; ``` -------------------------------- ### Disable Auto-Scroll Globally (JS) Source: https://github.com/lomray-software/after.js/blob/master/README.md This snippet shows how to disable the default auto-scroll behavior globally by passing `scrollToTop: false` to the `render` function in your server setup file (e.g., `./src/server.js`). ```javascript // ./src/server.js const scrollToTop = false; const html = await render({ req, res, routes, chunks, scrollToTop, }); ``` -------------------------------- ### Disabling After.js Auto-Scroll Globally in Node.js Source: https://github.com/lomray-software/after.js/blob/master/packages/after.js/README.md Demonstrates how to disable the default auto-scroll behavior when the URL changes by passing `scrollToTop: false` to the `render` function in the server-side rendering setup. ```JavaScript // ./src/server.js const scrollToTop = false; const html = await render({ req, res, routes, chunks, scrollToTop, }); ``` -------------------------------- ### Building and Exporting After.js Static Site using Yarn Source: https://github.com/lomray-software/after.js/blob/master/packages/after.js/README.md Provides the command-line steps using Yarn to build the After.js application and then run the export script to generate the static files. ```Bash yarn build yarn export ``` -------------------------------- ### Configuring Page Transition Behavior Source: https://github.com/lomray-software/after.js/blob/master/packages/after.js/README.md This snippet shows how to configure the page transition behavior in `client.js` by passing the `transitionBehavior` prop to the `` component. Setting it to "instant" allows the next page to render immediately while `getInitialProps` is still pending. ```javascript // ./src/client.js // transitionBehavior = blocked | instant ensureReady(routes).then(data => hydrate( , document.getElementById('root') ) ); ``` -------------------------------- ### Build and Export Static Site (Bash) Source: https://github.com/lomray-software/after.js/blob/master/README.md These commands are used after setting up the `static_export.js` file to build the After.js application and then run the export script to generate the static site files. ```bash yarn build yarn export ``` -------------------------------- ### Handling Dynamic 404 via getInitialProps in After.js Source: https://github.com/lomray-software/after.js/blob/master/packages/after.js/README.md This snippet shows the recommended After.js approach for dynamic 404s. By returning `{ statusCode: 404 }` from `getInitialProps` when a resource is not found, After.js automatically renders the configured 404 fallback component. ```javascript function ProductPage({ product }) { return

{product.name}

; } ProductPage.getInitialProps = async ({ match }) => { try { const { data } = await fetchProduct(match.params.slug); return { product: data }; } catch (error) { if (error.response.status === 404) return { statusCode: 404 }; return { error }; } }; ``` -------------------------------- ### Defining Application Routes Source: https://github.com/lomray-software/after.js/blob/master/packages/after.js/README.md This snippet illustrates how to define application routes using an array of route objects in `routes.js`, specifying the path, exact match requirement, and the component to render for each route. ```javascript // ./src/routes.js import Home from './Home'; import About from './About'; import Detail from './Detail'; // Internally these will become: // } /> const routes = [ { path: '/', exact: true, component: Home, }, { path: '/about', component: About, }, { path: '/detail/:id', component: Detail, }, ]; export default routes; ``` -------------------------------- ### Configuring babel-plugin-after via .babelrc (JSON) Source: https://github.com/lomray-software/after.js/blob/master/packages/babel-plugin-after/README.md Basic configuration for enabling the babel-plugin-after in a .babelrc file. ```json { "plugins": ["after"] } ``` -------------------------------- ### Setting Transition Behavior on After Component Source: https://github.com/lomray-software/after.js/blob/master/README.md Demonstrates how to control the page transition behavior by passing the `transitionBehavior` prop to the `` component. Setting it to "instant" allows the next page to render immediately while `getInitialProps` is still pending. ```js // ./src/client.js // transitionBehavior = blocked | instant ensureReady(routes).then(data => hydrate( , document.getElementById('root') ) ); ``` -------------------------------- ### Configuring Code Splitting with asyncComponent in After.js Source: https://github.com/lomray-software/after.js/blob/master/packages/after.js/README.md This snippet shows how to configure a route for code splitting in After.js using the `asyncComponent` helper. It requires a `loader` function that dynamically imports the component and optionally accepts a `Placeholder` component to show while loading. ```javascript // ./src/_routes.js import React from 'react'; import Home from './Home'; import { asyncComponent } from '@jaredpalmer/after'; export default [ // normal route { path: '/', exact: true, component: Home, }, // codesplit route { path: '/about', exact: true, component: asyncComponent({ loader: () => import('./About'), // required Placeholder: () =>
...LOADING...
, // this is optional, just returns null by default }), }, ]; ``` -------------------------------- ### Implementing Data Fetching with getInitialProps (JavaScript) Source: https://github.com/lomray-software/after.js/blob/master/packages/after.js/README.md Shows a React component (`About`) that defines a static asynchronous method `getInitialProps`. This method is used to fetch data (`stuff`) before rendering the component, making the data available via `this.props`. It illustrates server-side rendering data fetching and subsequent client-side fetching. ```JavaScript // ./src/About.js import React from 'react'; import { NavLink } from 'react-router-dom'; class About extends React.Component { static async getInitialProps({ req, res, match }) { const stuff = await CallMyApi(); return { stuff }; } render() { return (
Home About

About

{this.props.stuff}
); } } export default About; ``` -------------------------------- ### Configuring After.js Static Export in Node.js Source: https://github.com/lomray-software/after.js/blob/master/packages/after.js/README.md Defines the `render` and `routes` functions required for After.js static site generation. The `render` function uses `renderStatic` to generate HTML and data, while `routes` specifies the paths to be exported. Requires `@jaredpalmer/after` and manifest files. ```JavaScript // ./src/static_export.js import { renderStatic } from '@jaredpalmer/after'; import appRoutes from './routes'; const assets = require(process.env.RAZZLE_ASSETS_MANIFEST); const chunks = require(process.env.RAZZLE_CHUNKS_MANIFEST); export const render = async (req, res) => { const { html, data } = await renderStatic({ req, res, routes: appRoutes, assets, chunks, }); res.json({ html, data }); }; export const routes = async () => { return ['/', '/about']; }; ``` -------------------------------- ### Defining Parameterized Routes with React Router Source: https://github.com/lomray-software/after.js/blob/master/README.md Illustrates how to define route configurations using an array of objects, which are then used by After.js and React Router. This includes defining routes with exact paths and parameterized paths like `/detail/:id`. ```js // ./src/routes.js import Home from './Home'; import About from './About'; import Detail from './Detail'; // Internally these will become: // } /> const routes = [ { path: '/', exact: true, component: Home, }, { path: '/about', component: About, }, { path: '/detail/:id', component: Detail, }, ]; export default routes; ``` -------------------------------- ### Configure After.js Static Export (JS) Source: https://github.com/lomray-software/after.js/blob/master/README.md This snippet shows the required `render` and `routes` functions for `./src/static_export.js`. The `render` function uses `renderStatic` to generate HTML and data, while the `routes` function specifies the paths to be statically generated. ```javascript // ./src/static_export.js import { renderStatic } from '@jaredpalmer/after'; import appRoutes from './routes'; const assets = require(process.env.RAZZLE_ASSETS_MANIFEST); const chunks = require(process.env.RAZZLE_CHUNKS_MANIFEST); export const render = async (req, res) => { const { html, data } = await renderStatic({ req, res, routes: appRoutes, assets, chunks, }); res.json({ html, data }); }; export const routes = async () => { return ['/', '/about']; }; ``` -------------------------------- ### Fetching Data with getInitialProps and Nested Routes Source: https://github.com/lomray-software/after.js/blob/master/README.md Shows a React component using the static `getInitialProps` method to fetch data based on route parameters (`match.params.id`). It also demonstrates rendering nested React Router `` components within the main component's render method. ```js // ./src/Detail.js import React from 'react'; import { Route } from 'react-router-dom'; class Detail extends React.Component { // Notice that this will be called for // /detail/:id // /detail/:id/more // /detail/:id/other static async getInitialProps({ req, res, match }) { const item = await CallMyApi(`/v1/item${match.params.id}`); return { item }; } render() { return (

Detail

{this.props.item}
{this.props.item.more}
} />
{this.props.item.other}
} />
); } } export default Detail; ``` -------------------------------- ### Implementing Custom Async Renderer with Apollo and After.js Source: https://github.com/lomray-software/after.js/blob/master/packages/after.js/README.md This snippet sets up an Express server using After.js, demonstrating how to integrate Apollo Client's SSR capabilities (getDataFromTree, client.extract) into a custom renderer function. The custom renderer fetches data using Apollo before rendering to string and returns the HTML and initial Apollo state. ```js // ./src/server.js import React from 'react'; import express from 'express'; import { render } from '@jaredpalmer/after'; import { renderToString } from 'react-dom/server'; import { ApolloProvider, getDataFromTree } from 'react-apollo'; import routes from './routes'; import createApolloClient from './createApolloClient'; import Document from './Document'; const chunks = require(process.env.RAZZLE_CHUNKS_MANIFEST); const server = express(); server .disable('x-powered-by') .use(express.static(process.env.RAZZLE_PUBLIC_DIR)) .get('/*', async (req, res) => { const client = createApolloClient({ ssrMode: true }); const customRenderer = node => { const App = {node}; return getDataFromTree(App).then(() => { const initialApolloState = client.extract(); const html = renderToString(App); return { html, initialApolloState }; }); }; try { const html = await render({ req, res, routes, chunks, customRenderer, document: Document, }); res.send(html); } catch (error) { console.error(error); res.json({ message: error.message, stack: error.stack }); } }); export default server; ``` -------------------------------- ### Implementing Custom Async Rendering with Apollo and After.js Source: https://github.com/lomray-software/after.js/blob/master/README.md This code snippet demonstrates setting up an Express server to handle requests and use After.js for server-side rendering. It defines a customRenderer function that integrates Apollo Client's getDataFromTree to fetch data before rendering, ensuring the initial state is available on the server. The custom renderer returns the rendered HTML and the initial Apollo state. ```javascript // ./src/server.js import React from 'react'; import express from 'express'; import { render } from '@jaredpalmer/after'; import { renderToString } from 'react-dom/server'; import { ApolloProvider, getDataFromTree } from 'react-apollo'; import routes from './routes'; import createApolloClient from './createApolloClient'; import Document from './Document'; const chunks = require(process.env.RAZZLE_CHUNKS_MANIFEST); const server = express(); server .disable('x-powered-by') .use(express.static(process.env.RAZZLE_PUBLIC_DIR)) .get('/*', async (req, res) => { const client = createApolloClient({ ssrMode: true }); const customRenderer = node => { const App = {node}; return getDataFromTree(App).then(() => { const initialApolloState = client.extract(); const html = renderToString(App); return { html, initialApolloState }; }); }; try { const html = await render({ req, res, routes, chunks, customRenderer, document: Document, }); res.send(html); } catch (error) { console.error(error); res.json({ message: error.message, stack: error.stack }); } }); export default server; ``` -------------------------------- ### Handling Dynamic Imports (JavaScript) Source: https://github.com/lomray-software/after.js/blob/master/packages/babel-plugin-after/README.md Illustrates how the plugin handles dynamic imports with template literals, using '[request]' for webpackChunkName and the variable name for chunkName. ```javascript const name = "SlimShady" { path: "/rap/god", component: asyncComponent({ loader: () => import( `./pages/${name}` ) }) } ``` ```javascript const name = "SlimShady" { path: "/rap/god", component: asyncComponent({ loader: () => import( /* webpackChunkName: '[request]' */ `./pages/${name}` ), chunkName: name, }) } ``` -------------------------------- ### Configuring Static 404 Route in After.js Source: https://github.com/lomray-software/after.js/blob/master/packages/after.js/README.md This snippet shows how to define a default 404 fallback component in the `routes.js` file for React Router to pick up when no path matches. It imports the necessary components and exports an array of route configurations. ```javascript // ./src/routes.js import React from 'react'; import Home from './Home'; import Notfound from './Notfound'; import { asyncComponent } from '@jaredpalmer/after'; export default [ // normal route { path: '/', exact: true, component: Home, }, // 404 route { // there is no need to declare path variable // react router will pick this component as fallback component: Notfound, }, ]; ``` -------------------------------- ### Transforming Basic asyncComponent Usage (JavaScript) Source: https://github.com/lomray-software/after.js/blob/master/packages/babel-plugin-after/README.md Demonstrates how the plugin adds a webpackChunkName magic comment and a chunkName property based on the imported path when neither is initially present. ```javascript { path: "/product/:name", component: asyncComponent({ loader: () => import( `./pages/ProducDetail` ) }) } ``` ```javascript { path: "/product/:name", component: asyncComponent({ loader: () => import( /* webpackChunkName: 'pages-ProducDetail' */ `./pages/ProducDetail` ) chunkName: "pages-ProducDetail", }) } // 👆 as you can see `./pages/ProducDetail` changed to `pages-ProducDetail`, // because for web servers `/` means a folder // and webpackChunkName is name of file that saved on disk, // so `/` in file name may break our app ``` -------------------------------- ### Handling Dynamic 404s via getInitialProps in After.js Source: https://github.com/lomray-software/after.js/blob/master/README.md This snippet shows the recommended After.js approach for dynamic 404s. Instead of handling the error in the component's render, the 'getInitialProps' function catches the 404 error from the API and returns '{ statusCode: 404 }'. After.js intercepts this return value and automatically renders the 404 fallback component defined in 'routes.js'. ```javascript function ProductPage({ product }) { return

{product.name}

; } ProductPage.getInitialProps = async ({ match }) => { try { const { data } = await fetchProduct(match.params.slug); return { product: data }; } catch (error) { if (error.response.status === 404) return { statusCode: 404 }; return { error }; } }; ``` -------------------------------- ### Implementing Parameterized Routes and getInitialProps Source: https://github.com/lomray-software/after.js/blob/master/packages/after.js/README.md This snippet demonstrates a React component (`Detail.js`) that uses parameterized routing (`/detail/:id`). It shows how to access route parameters (`match.params.id`) within the static `getInitialProps` method to fetch data and how to render nested routes using React Router's `` component. ```javascript // ./src/Detail.js import React from 'react'; import { Route } from 'react-router-dom'; class Detail extends React.Component { // Notice that this will be called for // /detail/:id // /detail/:id/more // /detail/:id/other static async getInitialProps({ req, res, match }) { const item = await CallMyApi(`/v1/item${match.params.id}`); return { item }; } render() { return (

Detail

{this.props.item}
{this.props.item.more}
} />
{this.props.item.other}
} />
); } } export default Detail; ``` -------------------------------- ### Implementing getInitialProps in a React Component Source: https://github.com/lomray-software/after.js/blob/master/README.md This JavaScript snippet shows how to add a static async getInitialProps method to a React component. This method is called on both server render and client mounts to fetch data, which is then made available to the component via this.props. It demonstrates fetching data using a placeholder CallMyApi function and rendering it. ```js // ./src/About.js import React from 'react'; import { NavLink } from 'react-router-dom'; class About extends React.Component { static async getInitialProps({ req, res, match }) { const stuff = await CallMyApi(); return { stuff }; } render() { return (
Home About

About

{this.props.stuff}
); } } export default About; ``` -------------------------------- ### Passing Custom Params to getInitialProps (Server) Source: https://github.com/lomray-software/after.js/blob/master/packages/after.js/README.md This snippet demonstrates how to pass custom parameters from the server-side rendering logic in `server.js` to the `ctx` object available within `getInitialProps` functions. ```javascript // ./src/server.js ... try { const html = await render({ req, res, routes, chunks, // Anything else you add here will be made available // within getInitialProps(ctx) // e.g a redux store... customThing: 'thing', }); res.send(html); } catch (error) { console.error(error); res.json({ message: error.message, stack: error.stack }); } ... ``` -------------------------------- ### Wrap App in Layout (client.js) Source: https://github.com/lomray-software/after.js/blob/master/examples/layout-component/README.md Modify the client.js file to wrap the entire application root with a Layout component during the hydration process. ```js // client.js ensureReady(routes).then(data => hydrate( , document.getElementById('root') ) ); ``` -------------------------------- ### Defining Custom After.js Document Component (Basic) Source: https://github.com/lomray-software/after.js/blob/master/packages/after.js/README.md This snippet shows how to create a basic custom Document component in After.js. It overrides the default HTML structure, uses React Helmet for managing document head attributes, and includes standard After.js components like AfterRoot, AfterData, AfterScripts, and AfterStyles. ```JavaScript // ./src/Document.js import React from 'react'; import { AfterRoot, AfterData, AfterScripts, AfterStyles, } from '@jaredpalmer/after'; class Document extends React.Component { static async getInitialProps({ renderPage }) { const page = await renderPage(); return { ...page }; } render() { const { helmet } = this.props; // get attributes from React Helmet const htmlAttrs = helmet.htmlAttributes.toComponent(); const bodyAttrs = helmet.bodyAttributes.toComponent(); return ( Welcome to the Afterparty {helmet.title.toComponent()} {helmet.meta.toComponent()} {helmet.link.toComponent()} ); } } export default Document; ``` -------------------------------- ### Using Custom After.js Document in Server Render Source: https://github.com/lomray-software/after.js/blob/master/packages/after.js/README.md This snippet illustrates how to configure the After.js server to use a custom Document component. It imports the custom Document and passes it to the render function's 'document' option, enabling the server to render the application using the specified HTML structure. ```JavaScript // ./src/server.js import express from 'express'; import { render } from '@jaredpalmer/after'; import routes from './routes'; import MyDocument from './Document'; const chunks = require(process.env.RAZZLE_CHUNKS_MANIFEST); const server = express(); server .disable('x-powered-by') .use(express.static(process.env.RAZZLE_PUBLIC_DIR)) .get('/*', async (req, res) => { try { // Pass document in here. const html = await render({ req, res, document: MyDocument, chunks, routes, }); res.send(html); } catch (error) { console.error(error); res.json({ message: error.message, stack: error.stack }); } }); export default server; ``` -------------------------------- ### Handling Existing chunkName Property (JavaScript) Source: https://github.com/lomray-software/after.js/blob/master/packages/babel-plugin-after/README.md Demonstrates that if a chunkName property is already provided, the plugin uses its value for both the webpackChunkName magic comment and the chunkName property. ```javascript { path: "/test", component: asyncComponent({ loader: () => import( `./pages/test` ), chunkName: "my-custom-chunk-name", }) } ``` ```javascript { path: "/test", component: asyncComponent({ loader: () => import( /* webpackChunkName: 'my-custom-chunk-name' */ `./pages/test` ), chunkName: "my-custom-chunk-name", }) } ``` -------------------------------- ### Passing Custom Params to getInitialProps (Server) Source: https://github.com/lomray-software/after.js/blob/master/README.md Demonstrates how to extend the context object passed to `getInitialProps` by adding custom properties in the `render` function on the server side. This allows server-specific data or objects (like a Redux store) to be available during server-side data fetching. ```js // ./src/server.js ... try { const html = await render({ req, res, routes, chunks, // Anything else you add here will be made available // within getInitialProps(ctx) // e.g a redux store... customThing: 'thing', }); res.send(html); } catch (error) { console.error(error); res.json({ message: error.message, stack: error.stack }); } ... ``` -------------------------------- ### Configuring babel-plugin-after Source: https://github.com/lomray-software/after.js/blob/master/UPGRADING.md Provides the configuration for the `.babelrc` file to enable the `babel-plugin-after` plugin. This plugin automates the process of adding `webpackChunkName` and `chunkName` to `asyncComponent` definitions, eliminating the need for manual changes in the routes file. ```json { "presets": [ "razzle/babel" ], "plugins": [ "after" ] } ``` -------------------------------- ### Defining Code-Split Routes in After.js Source: https://github.com/lomray-software/after.js/blob/master/README.md This snippet shows how to configure lazy-loaded or code-split routes in After.js. Instead of directly assigning a component, the 'component' property uses 'asyncComponent' from '@jaredpalmer/after'. The 'loader' function uses dynamic 'import()' to load the component asynchronously, and an optional 'Placeholder' component can be provided to show while loading. ```javascript // ./src/_routes.js import React from 'react'; import Home from './Home'; import { asyncComponent } from '@jaredpalmer/after'; export default [ // normal route { path: '/', exact: true, component: Home, }, // codesplit route { path: '/about', exact: true, component: asyncComponent({ loader: () => import('./About'), // required Placeholder: () =>
...LOADING...
, // this is optional, just returns null by default }), }, ]; ``` -------------------------------- ### Passing Custom Params to After Component (Client) Source: https://github.com/lomray-software/after.js/blob/master/packages/after.js/README.md This snippet shows how to pass custom parameters from the client-side hydration logic in `client.js` to the `` component, making them available in the `ctx` object for `getInitialProps`. ```javascript // ./src/client.js ... ensureReady(routes).then(data => hydrate( {/* Anything else you pass to will be made available within getInitialProps(ctx) e.g a redux store... */} , document.getElementById('root') ) ); ... ``` -------------------------------- ### Custom Document with styled-components Integration in After.js Source: https://github.com/lomray-software/after.js/blob/master/README.md This snippet demonstrates how to integrate styled-components with a custom After.js Document component. It uses ServerStyleSheet in getInitialProps to collect styles during server rendering by wrapping the App component. The collected style tags are then injected into the of the HTML document. ```javascript // ./src/Document.js import React from 'react'; import { ServerStyleSheet } from 'styled-components'; import { AfterRoot, AfterData, AfterScripts } from '@jaredpalmer/after'; export default class Document extends React.Component { static async getInitialProps({ renderPage }) { const sheet = new ServerStyleSheet(); const page = await renderPage(App => props => sheet.collectStyles() ); const styleTags = sheet.getStyleElement(); return { ...page, styleTags }; } render() { const { helmet, styleTags } = this.props; // get attributes from React Helmet const htmlAttrs = helmet.htmlAttributes.toComponent(); const bodyAttrs = helmet.bodyAttributes.toComponent(); return ( {helmet.title.toComponent()} {helmet.meta.toComponent()} {helmet.link.toComponent()} {/* here is where we put our Styled Components styleTags... */} {styleTags} ); } } ``` -------------------------------- ### Defining Custom After.js Document Component with styled-components Source: https://github.com/lomray-software/after.js/blob/master/packages/after.js/README.md This snippet demonstrates integrating styled-components with a custom After.js Document component. It uses ServerStyleSheet to collect styles during server-side rendering and injects them into the document head using getStyleElement(). It also utilizes renderPage() to wrap the main application component. ```JavaScript // ./src/Document.js import React from 'react'; import { ServerStyleSheet } from 'styled-components'; import { AfterRoot, AfterData, AfterScripts } from '@jaredpalmer/after'; export default class Document extends React.Component { static async getInitialProps({ renderPage }) { const sheet = new ServerStyleSheet(); const page = await renderPage(App => props => sheet.collectStyles() ); const styleTags = sheet.getStyleElement(); return { ...page, styleTags }; } render() { const { helmet, styleTags } = this.props; // get attributes from React Helmet const htmlAttrs = helmet.htmlAttributes.toComponent(); const bodyAttrs = helmet.bodyAttributes.toComponent(); return ( {helmet.title.toComponent()} {helmet.meta.toComponent()} {helmet.link.toComponent()} {/* here is where we put our Styled Components styleTags... */} {styleTags} ); } } ``` -------------------------------- ### Identifying asyncComponent Usage Pattern (JavaScript) Source: https://github.com/lomray-software/after.js/blob/master/packages/babel-plugin-after/README.md Illustrates the specific object structure the plugin searches for: an object property named 'component' whose value is a call to the identified asyncComponent function. ```javascript import { asyncComponent } from '@jaredpalmer/after'; // localname is asyncComponent // let's look for localname (`asyncComponent`) and see where it get called // ... // oh nice I found a call to that function { component: asyncComponent({ loader: () => import( `./pages/ProducDetail` ) }), } // now let me check and see if it's value of an object propery that named `component` { // <- it's an object // 👇 and property name is `component` component: asyncComponent({ loader: () => import( `./pages/ProducDetail` ) }) } ``` -------------------------------- ### Handling Existing webpackChunkName (JavaScript) Source: https://github.com/lomray-software/after.js/blob/master/packages/babel-plugin-after/README.md Shows that if a webpackChunkName magic comment already exists, the plugin uses its value for both the magic comment and the added chunkName property. ```javascript { path: "/product/:name", component: asyncComponent({ loader: () => import( /* webpackChunkName: 'HelloWorld' */ `./pages/ProducDetail` ) }) } ``` ```javascript { path: "/product/:name", component: asyncComponent({ loader: () => import( /* webpackChunkName: 'HelloWorld' */ `./pages/ProducDetail` ), chunkName: "HelloWorld", }) } ``` -------------------------------- ### Passing Custom Params to After Component (Client) Source: https://github.com/lomray-software/after.js/blob/master/README.md Shows how to pass custom properties to the `` component during client-side hydration. These props are then made available within the `ctx` object in `getInitialProps` when it's called on the client. ```js // ./src/client.js ... ensureReady(routes).then(data => hydrate( {/* Anything else you pass to will be made available within getInitialProps(ctx) e.g a redux store... */} , document.getElementById('root') ) ); ... ```