Skip to content

Latest commit

 

History

History
434 lines (280 loc) · 24.4 KB

File metadata and controls

434 lines (280 loc) · 24.4 KB

Unly logo

Dependencies

Documentation about the project's dependencies


Dependencies

Overview of the project deps, why we use them, and (not always) quick explanations about them

All the packages listed here are under open source, non-restrictive license (MIT, ISC, etc.)

The order follows the order in package.json (kinda alphabetical but not quite exactly ¯\_(ツ)_/¯)

Amplitude

A JavaScript SDK for tracking events and revenue to Amplitude.

When your want to perform Analytics in any app, people usually go for Google Analytics. We don't. GA is too limited, and huge, with tons of useless stuff. We've used it, and we really don't recommend it for any SPA, especially when playing with universal app because it just sucks.

It's very hard to configure GA with universal apps, you'll end up with wrong analytics insights due to event multi triggers (SSR + CSR). It was built for another world. Not for SPA!

Instead, we use (and recommend) Amplitude instead. The world of analytics is huge, and isn't cheap.

  • amplitude-js: Top-level amplitude official lib, used by react-amplitude.
  • @amplitude/react-amplitude: React-friendly amplitude lib, non-officially maintained. Really useful when working with react.

Amplitude allows to track events and users behaviour, who are two very different things, even if events are related to users.

A note about Amplitude's pricing

Amplitude offers a free plan that allows 10 million events per months ($identity events aren't counted towards events, they're free).

Then, the cheapest plan is Growth, that starts around $48k/year (yup, it's a huge gap)

If you want to benefit from the Growth plan for free, know that it's possible (but limited to 1 years), through their startup Scholarship. They offer Scholarship for non-profit organisation too.

But, a word of caution here, even if you benefit from the scholarship, make sure your business doesn't rely on Growth features when your Scholarship ends.

They told us then always find a way to provide Amplitude at an acceptable price for non-profit

Anyway, Amplitude is one of the best out there for Analytics, if the free plan is enough for your needs, or if you can afford paid plans. Also, their react integration is really good, even though it's not officially maintained and could use some love.


Emotion

Emotion is a library designed for writing css styles with JavaScript. https://emotion.sh/docs/introduction

Next.js provides CSS-in-js using styled-jsx, but we dislike it for several reasons. It's not very intuitive to write styles that way and it needs extra dependencies/configuration to work with nested components and such.

Instead, we use Emotion in this project, which allows to write components using either the styled notation, or the css notation.

It's strongly recommended to read the official documentation about how to use it.

Note about /** @jsx jsx */

When using Emotion, the file must start with /** @jsx jsx */ on top of it.

TL;DR It basically tells the babel compiler to do something different and won't work if not specified.

Sentry

Sentry provides open-source and hosted error monitoring that helps all software teams discover, triage, and prioritize errors in real-time.

We use Sentry to catch errors that happen within the application. They are available at https://sentry.io/ for any developers in the team.

Those errors are also sent to our Slack channel sentry-monitoring.

Sentry provides 2 different packages, with different abilities (but a very similar API) for browser and server usage.

A note about Sentry usage

In the source code, we always use @sentry/node, which is automatically converted at build step by babel. (see next.config.js)

This way, we always use the same import, which is linked to the right package based on the runtime engine target.


Unly packages

We use some of our own packages. They are all hosted on ou GitHub repository, and all under MIT license.

  • @unly/utils: This is a utility library which contains various helpers. This repository was created because those helpers are used amongst several projects and were copy/pasted, which is a bad practice.
  • @unly/utils-simple-logger: Logger based on Winston with sane default so that it only logs error in production and filter other logs, while keeping them all in non-production environments. Basically avoids to increase cost by logging useless logs in production.
  • @unly/universal-language-detector: Language detector that works universally (browser + server) - Meant to be used with a universal framework, such as Next.js

React Apollo allows you to fetch data from your GraphQL server and use it in building complex and reactive UIs using the React framework. React Apollo may be used in any context that React may be used.

  • apollo-boost: Apollo Boost is a zero-config way to start using Apollo Client. It includes some sensible defaults, such as our recommended InMemoryCache and HttpLink, which come configured for you with our recommended settings. Even though it may seems unused, this package is required as peer-dependency.
  • apollo-cache-inmemory: apollo-cache-inmemory is the recommended cache implementation for Apollo Client 2.0. InMemoryCache is a normalized data store that supports all of Apollo Client 1.0's features without the dependency on Redux.
  • apollo-client: Apollo Client is a fully-featured caching GraphQL client with integrations for React, Angular, and more. It allows you to easily build UI components that fetch data via GraphQL.
  • apollo-link-http: The http link is a terminating link that fetches GraphQL results from a GraphQL endpoint over an http connection.
  • apollo-link-context: Easily set a context on your operation, which is used by other links further down the chain.
  • react-apollo: React Apollo allows you to fetch data from your GraphQL server and use it in building complex and reactive UIs using the React framework. React Apollo may be used in any context that React may be used. In the browser, in React Native, or in Node.js when you want to do server-side rendering.

It works fine with both SSR and client-side navigation.


classnames

classnames is just the must-have tool to use to manipulate dynamic className property

  • classnames: A simple JavaScript utility for conditionally joining classNames together.

Cookies

It's hard (or at least, non-trivial) to make cookies work universally with Next.js

  • js-cookie: Used to WRITE cookies from the client side. A simple, lightweight JavaScript API for handling browser cookies
  • cookies: Used to WRITE cookies from the server side. Cookies is a node.js module for getting and setting HTTP(S) cookies. Cookies can be signed to prevent tampering, using Keygrip. It can be used with the built-in node.js HTTP library, or as Connect/Express middleware. I'm not sure if that lib is the best choice, but it did work back then. Other alternative may be https://github.com/maticzav/nookies
  • next-cookies: Used to READ cookies universally (cannot write). Tiny little function for getting cookies on both client & server with next.js. This enables easy client-side and server-side rendering of pages that depend on cookies.

A cookies prop is available to all Page and Layout components (through the _app.tsx:render()).

Why not using universal-cookie?

universal-cookie looks promising and if you know about it, you may ask yourself why we don't use it instead of one package for the client side, and another one for the server side.

Well, the answer is straightforward: It does not work. See ItsBenCodes/cookies#256

Cookies management abstraction UniversalCookiesManager

We've built our own UniversalCookiesManager utility class to deal with cookies in a universal way (same API on client/server sides).

It basically hides away the complexity, and allows for source code reusability.


css-to-react-native

Converts CSS text to a React Native stylesheet object.

Converts all number-like values to numbers, and string-like to strings.

Automatically converts indirect values to their React Native equivalents.

Used to dynamically convert CSS to React style object, for CSS rules coming from a data source (such as GraphCMS).

Currently used by GraphCMSAsset.tsx


deepmerge

Merges the enumerable properties of two or more objects deeply.

Used in many places to merge different objects together. Handles deeply nested objects.


GraphQL

  • graphql: Client for connecting to a GraphQL endpoint.
  • graphql-tag: Helpful utilities for parsing GraphQL queries. Useful to write plain-text GraphQL query using the gql tag, that can be validated by other tools, such as JS GraphQL IntelliJ Plugin.
  • JS GraphQL IntelliJ Plugin: GraphQL language support for WebStorm, IntelliJ IDEA and other IDEs based on the IntelliJ Platform. The plugin is available using WebStorm directly. To install it, open your IDE "Settings", "Plugins", "Marketplace" and search for "GraphQL". But, it should be automatically made available by default. (through shared IDE config)

The usage of both gql and the IntelliJ GraphQL plugin is awesome, it allows to write GraphQL queries (see gql folder) and have auto-completion and validation from WebStorm itself.

To refresh the GraphQL spec, just run the .graphqlconfig file by opening it and run the stage you want to sync (usually staging).


I18n, i18next and Locize

TODO


json-stringify-safe

Used to safely stringify JSON objects. Works even when they have circular dependencies

Use at your convenience. We weren't sure whether to use json-stringify-safe or safe-json-stringify and we made a wild choice here.


A modern JavaScript utility library delivering modularity, performance & extras.

We made the choice to import lodash packages one-by-one instead of loading the whole lodash lib directly. We're not sure if it's better/easier/wiser. We suppose it should decrease the bundle size, but maybe it's natively handled by tree-shacking?

We use plenty of utilities from lodash. Make sure read their documentation.

Note about Lodash TS typings

We also load each TS types one-by-one. One advantage of that is that we can decide not to load typings that do not work.

For instance, we tried using @types/lodash.filter but eventually removed it because it creates a mess that is hard to deal with. Typings may be wrong and breaks our tests, in such case it's nice to have the flexibility not to use them.


Next

Next.js framework package and plugins/utilities.


React

React package and plugins/utilities.

  • react: React is a JavaScript library for creating user interfaces.
  • react-apollo: React Apollo allows you to fetch data from your GraphQL server and use it in building complex and reactive UIs using the React framework. React Apollo may be used in any context that React may be used. In the browser, in React Native, or in Node.js when you want to do server-side rendering.
  • react-dom: This package serves as the entry point to the DOM and server renderers for React. It is intended to be paired with the generic React package, which is shipped as react to npm.
  • react-style-proptype: Validates style objects by ensuring the keys are valid css property names (in camelcase form).
  • prop-types: Runtime type checking for React props and similar objects.

N.B: react and react-dom must always use the same version.


webfontloader

Web Font Loader gives you added control when using linked fonts via @font-face.

It provides a common interface to loading fonts regardless of the source, then adds a standard set of events you may use to control the loading experience.

The Web Font Loader is able to load fonts from Google Fonts, Typekit, Fonts.com, and Fontdeck, as well as self-hosted web fonts. It is co-developed by Google and Typekit.


winston

Peer-dependency of @unly/utils-simple-logger

  • winston: A logger for just about everything.

Dev dependencies

@types

TypeScript requires Typings to resolve types.

Those packages add additional types that allow TypeScript to resolve the related types, and allow for a better developer experience. Also, without some of those types, TS would fail to compile.

Sometimes, TS types are included in the same package as the main package, sometimes in a different package, such as for those below.


Those dependencies are used only during the development and aren't shipped to the end-user.

They are meant to make the development process easier/faster.

Now & Zeit

Official packages from Zeit/Now, the company hosting our application

Debug WebStorm

Packages meant to help with the debug of the application

  • concurrently: Run multiple commands concurrently.
  • cross-env: Run scripts that set and use environment variables across platforms.

Together, those two packages are used by the WebStorm "Debug" configuration. (top right)

Running the Debug configuration in debug mode allows to pause execution and use breakpoints.


Eslint

Eslint helps us enforce code style and check for typos and errors during the development process

Eslint rules are automatically used by WebStorm.

Eslint with TypeScript and JSX support was configured following this tutorial.

Run yarn lint to run the linter.


Tests

Jest is our test runner, it runs our tests to make sure we don't ship regressions to our end users

  • jest: Jest is a delightful JavaScript Testing Framework with a focus on simplicity.
  • jest-extended: Additional Jest matchers. Provides additional built-in tests for ease of testing.
  • react-test-renderer: This package provides an experimental React renderer that can be used to render React components to pure JavaScript objects, without depending on the DOM or a native mobile environment. Essentially, this package makes it easy to grab a snapshot of the "DOM tree" rendered by a React DOM or React Native component without using a browser or jsdom.
  • ts-jest: TypeScript preprocessor with source map support for Jest that lets you use Jest to test projects written in TypeScript.

Known issues:

Cypress

Cypress is a tool that helps performing end-to-end (E2E) tests that aim at testing the UI and the user workflows.

It is open source and free to use from the command line (doesn't count as Tests recording).

It also comes with a paid plan that provides a Dashboard, we use it with the Free plan, but it only allows 500 tests recordings per month.

Several utility scripts have been configured to help with E2E testing, each script takes an optional CYPRESS_STAGE environment variable, which defines the config file that will be used (development by default):

We used the following Cypress <> Next.js tutorial to get started. Note that our current installation doesn't provide test coverage. It's a bit harder to setup, here is a tutorial if ever needed.

N.B: Here is the documentation about the options available in the config files.


Documentation

  • markdown-toc: Generate a markdown TOC (table of contents). Uses many dependencies, many of them outdated (handlebars) and containing security issues, but we don't care much about those as they aren't shipped in the build, but only present on the developer's local machine.
  • version-bump-prompt: Used to make it easier to bump versions.