1.0.0
- 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
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 defaultru
anden
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:
- Run server
- Server runs webpack
- Webpack has 2 configs: server and client
- Build client
- Store client's stats (favicons-stats generated by
favicons-webpack-plugin
, webpack-stats generated byassets-webpack-plugin
) in/dist
folder - Get client's stats from
/dist
folder (using webpack alias) - Build server code
- Get built server code
- 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:
- 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.
Runnpm 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