Skip to content
This repository has been archived by the owner on Jan 1, 2024. It is now read-only.

1.0.0

Compare
Choose a tag to compare
@Metnew Metnew released this 04 Nov 19:21
· 382 commits to master since this release
  • LL with react-async-component
  • SSR works
  • Every route by default is lazy
  • Finally available in master
  • Requires feedback from Linux and Windows users.
  • Branch with the previous release.

But there is one problem: tiny-universal-skeleton is experimental and not so stable as I've thought before. So it's recommended to clean eslint errors (i.e. remove all eslint errors before quit from npm run dev)

Detailed:

Changes

Flow. Static typing

Yes, flow was added, because static typing is everywhere now and it's a good trend.
As you know there are only 2 leaders: TypeScript and Flow.
At first, Flow is easier for integration. TypeScript requires some additional changes.
Secondly, when you write js with flow - you still write js. When you write TypeScript - you write in another language, not in js. TypeScript has own ecosystem and it can make project unattractive for some developers.
Thirdly, flow is optional, so if you don't want flow - you can remove/ignore flow code and still work with a project.

Versioning

Versioning is important, especially for a starter, because It's always hard to migrate especially when code evolves fast. standard-version was added and now the project is following semver.

SUIR in the project

Bundle size was reduced using direct imports of CSS in src/client/index.jsx.
From 545 kb to 312 KB.
Only some elements are imported. If your app uses other components then you need to import more CSS files. Honestly, this bundle size reduction is better to be named "artificial".

SUIR in a wild

SUIR introduced some new components since a previous major update of the starter + semantic-ui-theme(SUIT) was created. SUIT is a good idea because it aims to bring CSS-in-JS in SUI, but repo currently is empty. Only some notes in issues.
Also, I'm still waiting on <Datepicker> in SUIR. Does anyone know when will it be released?

RSUIR -> SUIcrux

"React-semantic.ui-starter" is too long + it doesn't sound even in short form(RSUIR). + Project was radically changed since I've started it (June 2016 in another repo), since it has been mentioned on Reddit (and was in Github's "Trending" that day) and since it has been mentioned in SUIR repo. So I decided to rename the project.

The first variant was "Noir", but later I've found that package with name "noir" had already existed. So, I decided to pick another name. And it was really hard :)
SUIR mentioned this project in a readme, starter always has been using SUIR, so I decided to name it SUIcrux. I don't know what it can mean and how can it be translated, because English isn't my native language, but hope that it sounds better than "RSUIR".

Tests:

Reducers tests weren't changed.
Actions tests now use nock.
Jest snapshots were added.
Jest now resolves webpack aliases using babel-plugin-module-resolver.
Jest can resolve files (files were ignored in prev release if I remember correctly).
Jest can test styled-components, but this feature was turned off.
Test coverage increased from 81% to 89%.

It could be made even higher because xhr_wrapper util doesn't have own tests (but it'll have and probably will be separated in own repo).

Redux

Reducers' structure wasn't changed.

Redux code-splitting

Implement Redux code-splitting is one of the most important tasks currently.

Awral. Async action creator.

I have a project with >250 async actions. And one I realized that duplicating this code pattern across app is terrible:

export const GET_USER = id => async dispatch => {
	dispatch({type: 'GET_USER_PENDING'})
	const payload = await getUserFromServer(id)
	if (resultOK(payload)) {
		dispatch({type: 'GET_USER_SUCCESS', payload})
	} else {
		dispatch({type: 'GET_USER_FAIL', payload, error:true})
	}
	dispatch({type: 'GET_USER_FINALLY', payload})
}

So I've written Awral some time ago. It's a tiny util for async actions creation. And it allows to write async actions like:

export const GET_USERS = awral(getUsers)('GET_USERS')

Awral was added in the starter, but it can be easily replaced/removed.
Awral actions follow common action structure:

{
    error?: boolean,
    payload: any, // most commonly - API request result
    meta: any, // I propose to store arguments in this field
    type: string
}

Awral has smart API and it's only 910KB. It's highly recommended to check Awral sources before using it!

Lazy-Loading

Custom LazyLoad component was removed and replaced by react-async-component + react-async-bootstrapper. I check sources of these libs. Almost everything ok, except it forces root component to fires componentWillMount twice on the first render (If I remember correctly).

i18n

i18n-webpack-plugin forces you to make as many builds as many languages you have, so it was replaced with react-intl which allows making dynamic internationalisation.
i18n process is connected with SSR:

  • Get language from request Accept-Language header.
  • Get language translation from /locals
  • Render app on server + add window[variable] with localization data (only for this language!)
  • Respond with a rendered app.
  • Use translations and i18n stuff from on client.
    You can test i18n visiting app with different preferred languages in the browser. By default ru and en available.

Webpack

Added AutoDLLPlugin which makes builds significantly faster.
There is no spoon, Neo .html template. src/server/ssr/HTMLComponent.jsx creates html.
Many plugins like preload-webpack-plugin, html-webpack-plugin and other plugins were removed.

Complicated development/building cycle from tiny-universal-skeleton(more info in repo) was introduced here.

npm run dev shortly:

  1. Run server
  2. Server runs webpack
  3. Webpack has 2 configs: server and client
  4. Build client
  5. Store client's stats (favicons-stats generated by favicons-webpack-plugin, webpack-stats generated by assets-webpack-plugin) in /dist folder
  6. Get client's stats from /dist folder (using webpack alias)
  7. Build server code
  8. Get built server code
  9. Apply built server code to root server (server from step 1, which started webpack build )

This allows you to have both server and client hot-reloaded with no limitations: your server can have API, any middlewares, and etc.

NOTE:

  1. There is a problem - if code is invalid then webpack can't compile it and at step 8 you have undefined. Your code should always be valid else server may not start or/and may throw errors. This bug isn't so horrible as described and very rarely occurs, but keep in mind.
    Run npm run lint:scripts to lint scripts and detects eslint errors/warns.

Limitation probably will be fixed soon. Give me some time :)

SSR

Shortly:

  • Handle request by installed middlewares
  • Handle request by auth middleware:
    • add request.user property:
request.user = {
  isLoggedIn: boolean,
  token: string | void,
  username?: string,
  language: string 
}
  • create app based on request.useragent (detect is user on mobile device) and request.user
  • create preloadedState
  • get i18n data
  • create html
  • stream response

NOTE: data fetching issue isn't solved completely.

Other libraries

normalizr, reselect and immutable were removed.
react-ga included.

Redux-persist

More info here