Skip to content

topheman/nextjs-movie-browser

Repository files navigation

nextjs-movie-browser

Build Status Cypress Demo

This project is a NextJS implementation of the themoviedb.org website. The main goal was to dive deep into the NextJS framework with the following constaints/features:

  • SSR (Server Side Rendering): use NextJS to Server Side render the page with the data retrieved from the API and have a transparent client side navigation
    • critical-path CSS: extracting critical CSS is made easy using a CSS-in-JS library like styled-component
  • SEO friendly: server side render meta tags relative to content based on API result
  • Social Media cards friendly: server side render meta tags relative to twitter/facebook ... to customize thumbnails/description when page is shared (also works for slack, messenger, WhatsApp ...)
  • i18n
    • Support multi-language
      • From the API content
      • From the UI
    • Support Right-to-Left (rtl) languages such as Hebrew, Persian ...
    • Switch language on the fly
  • High quality project
    • code quality good practices (type checking, linting, unit/e2e testing, git hooks, cis ...)
    • automation / dev pipeline
    • documentation

Here is a list of some of the technologies I'm using:

ℹ️ The v1 was focused on SSR / i18n (backend and client behaviour), it has a basic design that lets you focus on those parts, the v2 is currently focused on the design part.

πŸ—’ Read the notes I took along the way.

Prerequisites

  • Nodejs v8
  • yarn / npm

Install

git clone https://github.com/topheman/nextjs-movie-browser.git
cd nextjs-movie-browser
yarn

You don't have yarn ? Run npm install - read more about why I'm using yarn.

Setup

This project uses the themoviedb.org api v3.

In your project, run the following (with your own api key):

./bin/initEnv.js --api-key YOUR_API_KEY

This will create two files: .env.local and .env.test.local (which won't be commited to git) with NEXTJS_APP_CLIENT_TMDB_API_KEY=YOUR_API_KEY.

That way, your api key will be taken in account directly in your development environment - read more about .env files.

Development

npm run dev

This will start a development server on http://localhost:3000.

Build

npm run build

This will build the a production version of the website in the .next folder.

Production

First, you need to build your project running npm run build, then:

npm start

This will launch a production server on http://localhost:3000.

You can change the port passing a PORT env var like: PORT=8080 npm start.

Test

The following command will run both unit and e2e (cypress) tests, in parallel:

npm test

You can choose to run them separately to have more readable logs (running in parallel unit and e2e tests runs faster but ends up with less readable logs).

Unit

You'll find unit tests spread in the src folder inside __tests__ folders in files named like *.spec.ts.

I'm using Jest as a test runner and react-testing-library as testing utilies.

  • npm run test:unit : single run of the unit tests
  • npm run test:unit:watch : run the unit tests in watch mode
  • npm run test:unit:coverage : run the unit tests collecting coverage infos in ./coverage folder.

End to end

End-to-end testing is a technique used to test whether the flow of an application right from start to finish is behaving as expected. The purpose of performing end-to-end testing is to identify system dependencies and to ensure that the data integrity is maintained between various system components and systems.

The entire application is tested for critical functionalities such as communicating with the other systems, interfaces, database, network, and other applications.

I'm using cypress.io for the e2e tests. You will find them in cypress/integration.

  • npm run test:cypress : single run the e2e tests. It will:
    • build the project and launch a production server at http://localhost:3000 (that way, your tests reflect exactly what the end user would see in production)
    • run the tests in cypress/integration folder
    • tear down once tests are passed (or failed)
  • npm run test:cypress:dev : use this one when you're coding your tests. It will:
    • spin up a dev server on http://localhost:3000 (so, you don't have to npm start)
    • open the cypress client that will let you choose which tests you want to run
  • npm run test:cypress:debug-build : use this if your e2e tests only fail on a production bundle, to debug the tests with the production version of your app. It will:
    • build the project and launch a production server at http://localhost:3000
    • open the cypress client that will let you choose which tests you want to run

Linter

I use tslint to check the coding style, with the following presets:

More on tslint configuration.

The following command will run the linter on your code base. This task is ran at pre-commit to ensure code quality.

npm run lint

Prettier

Prettier is a great tool to enforce a consistent style accross your code base (usefull when working in teams).

Here is how to integrate it with your editor.

Once it's done, when you'll save a file, it will reformat it.

The following command will let you format your code base. This task is ran at pre-commit.

npm run pretty

Environment files

Just like in create-react-app, you can use .env file to store your env vars that will be injected to your app.

Check my implementation

What .env file can be used ?

  • .env: Default.
  • .env.local: Local overrides. This file is loaded for all environments except test.
  • .env.development, .env.test, .env.production: Environment-specific settings.
  • .env.development.local, .env.test.local, .env.production.local: Local overrides of environment-specific settings.

Files on the left have more priority than files on the right:

  • npm run dev: .env.development.local, .env.development, .env.local, .env
  • npm run build / npm start: .env.production.local, .env.production, .env.local, .env
  • npm test: .env.test.local, .env.test, .env (note .env.local is missing)

Env vars are filtered before being injected:

  • NEXTJS_APP_CLIENT_*: will be accessible both client and server side (via process.env.NEXTJS_APP_CLIENT_*)
  • NEXTJS_APP_SERVER_*: will be accessible only server side (via process.env.NEXTJS_APP_SERVER_*) (you might wan't store env vars and not leek them to the frontend)

Deploy

See Heroku section in notes

Continuous Integration

Each git push triggers a test suite on travis. The following will be ran:

  • linting
  • type checking
  • unit tests
  • end to end test with cypress

The end to end test sessions are recorded, you can check them here.

Commit guidelines

To have uniform commit messages, I follow the AngularJS git commit guidelines, please take a look at it.

It also makes it easier to generate changelogs.

To generate changelog:

npm run generate-changelog -- v1.1.0 v1.2.0

Ready to be pasted to the github releases part.

FAQ

Versions

v2 (current)

This is a work in progress of the design part.

v1

The v1 has a strong setup for the SSR / SEO / i18n part also for code quality (type checking, linting, unit/e2e testing, git hooks ...).

It has a very basic design. I mainly focused on the NextJS part in order to do only design on the v2.

The code is available on this branch.

Precommit hook

Thanks to husky, you can simply add git hooks.

That way, once you install the project, you'll have a precommit hook installed. The following tasks are executed at each commit:

  • npm run lint: lints the project source code with tslint (both .js(x) and .ts(x) files)
  • npm run ts:check: type check .ts and .tsx files
  • npm test: runs in parallel unit and e2e tests

Next steps

  • Write more e2e / unit tests
  • Record and use mocks for e2e tests
  • Apply design to */cast and */seasons pages
  • Add missing translations (job / department descriptions for example)
  • Extract part of project
  • Mock next router - zeit/next.js: Issue #1827 #63fd29e
  • Write blog posts

Resources

This project is based on previous work:

More resources on the NOTES.md file.