1.0.0 • Published 5 years ago

@travelshift/web v1.0.0

Weekly downloads
-
License
UNLICENSED
Repository
-
Last release
5 years ago

Monorepo TS Next.js application

Setting up the local dev environment

  • run yarn --pure-lockfile. Also run it on the parent js folder
  • create .env file in this folder
  • run yarn dev

Try http://localhost:3000/book-holiday-trips/6-day-self-drive-tour-circle-of-iceland or some other known URL to confirm that everything is up and running.

Tests

We are using react-testing library as our testing framework. Tests are usually placed next to the tsx files with the .test.tsx extension.

yarn test will run your unit tests and npx jest --watchAll will watch for changes and re-run any test file that is modified.

We are not aiming for a 100% coverage but please do your best.

Deployment

Every branch is deployed automatically at creation, and redeployed when it's updated, to [branch-name]-web.branch.dev.traveldev.org and it will be live for 48hs. If you need it again after that time frame you can redeploy it from the CI.

Every merged branch will be deployed to production. There's no need to squash commits or any other cleaning up to get a PR merged, but please check that your merged branches were deleted.

Styles

For responsiveness we start from the mobile styles and override them with media queries to fit other resolutions.

On the React components we use emotion.js for CSS-in-JS which provides us with mixin-like structures, variables and so on.

The styles are kept in check by stylelint rules. This work almost seamlessly for the CSS-in-JS code.

Check CSS-in-JS notes & workarounds for more information.

Translations

We use ICU expression through i18next-icu and next-i18next libraries.

There's a <Trans/> component that should be used for i18n.

import { Trans } from "i18n";
const Content = () => {
    return (
      <Trans>Some i18n enabled string</Trans>
    )
  };

Also we have an useTranslation hooks for translating strings which is useful whenever the translated text can't be expressed as the content of a component (i.e. translating an attribute or sending a translation as a parameter)

import { useTranslation } from "i18n";
const FooterContainer = ({ theme }: Props) => {
  const { t } = useTranslation("footer");
  return (
    <Footer
      socialMediaSectionText={t("front_footer_social_media")}
    />
  );
};

Regarding the actual translation of strings we are not usually re-using those from the legacy pages but creating new ones.

Routing

Base routes are defined on src/shared/routes.ts

Data management

We are not using any state manager, just contexts and hooks.

To query GraphQL we have 1 query per page that's passed to the getInitialProps method

import tourQuery from "components/features/Tour/queries/TourQuery.graphql";

(TourPage as any).getInitialProps = () => ({
  namespacesRequired: ["common", "footer", "header"],
  query: tourQuery,
});

Queries are cached automatically by the server and on the client. There's a base Component to add apollo functionality to the other ones

import App from "next/app";
import withApolloClient from "lib/withApolloClient.jsx";
class MyApp extends App<Props> {
  // ...
}
export default withApolloClient(MyApp);

Optimizations

More references

Creating .env file with the following keys

CLIENT_API_URI=guidetoiceland.is
JAEGER_COLLECTOR_ENDPOINT=http://jaeger-collector.dev.traveldev.org/api/traces
JAEGER_SERVICE_NAME=<your-name>
SENTRY_DSN=<SENTRY_DSN_VALUE>

JAEGER_SERVICE_NAME will be useful for marking your logs with the jaeger service.

CSS-in-JS notes & workarounds

stylelint gets a bit confused when interpolating variables so the following syntax is a preferred way to sum up rules:

styled.div([
  hideScrollbar,
  css`
    height: calc(100% - 80px);
    overflow-y: scroll;
    overscroll-behavior: contain;
  `,
]);

Instead of directly interpolating hideScrollbar inside the css string template.

Lazy Hydration example

const TourContent = ({
  name,
  ribbon,
  valuePropositions,
  images,
  reviewTotalScore,
  reviewTotalCount,
  tourSections,
}: Props) => (
  <>
    <LazyHydrate whenIdle>
      <SectionNavigationBar sections={tourSections} />
    </LazyHydrate>
  </>
);

External links