Core Libraries

What I mean by “stack” are the packages Frontity is going to use by default.

  • UI: react & react-dom
  • State: overmind & overmind-react
  • CSS: @emotion/core & @emotion/styled
  • REST API: fetch (no package in client, polyfill in server)
  • Code Splitting: loadable-components
  • Head: react-helmet
  • Slots: react-slot-fill

It weights 331Kb.

npx package-size react,react-dom,overmind,overmind-react,@emotion/core,@emotion/styled,loadable-components,react-helmet,react-slot-fill --analyze

The previous stack weighted 926Kb:

  • UI: react & react-dom
  • State: mobx & mobx-state-tree & mobx-react
  • CSS: styled-components
  • REST API: wpapi & superagent
  • Code Splitting: react-universal-component
  • Head: react-helmet
  • Slots: react-slot-fill
npx package-size react,react-dom,mobx,mobx-state-tree,mobx-react,styled-components,wpapi,superagent,react-universal-component,react-helmet,react-slot-fill --analyze

So our starting bundle will weight only a third than the previous version :tada::tada:

I hope Lighthouse likes it more this time :slight_smile:

I have been thinking if we should interface some of those packages.

For example, use frontity/dynamic to interface loadable-components. That means users would do

import dynamic from 'frontity/dynamic'

const OtherComponent = dynamic(() => import('./OtherComponent'))

instead of

import loadable from '@loadable/component'

const OtherComponent = loadable(() => import('./OtherComponent'))

Same for the other packages:

import useStores from 'frontity/stores' 
// instead of
import { useOvermind } from 'overmind-react' 
import Head from 'frontity/head' 
// instead of
import { Helmet } from 'react-helmet' 
import { Slot, Fill } from 'frontity/slot-and-fill' 
// instead of
import { Slot, Fill } from 'react-slot-fill' 
import { css, styled } from 'frontity/styles' 
// instead of
import { css } from '@emotion/core' 
import { styled } from '@emotion/styled' 

It’s not to obscure that those packages are coming from their original packages but to help in package migrations. For example, in the future, we may move react-helmet to another, much smaller or much more performant package. This way the update won’t be major as long as the basic API remains the same and users won’t have to refactor their themes/extensions.

Interesting idea. Do we know some framework that is already doing this?

In Gatsby users directly import react-helmet when they install the react-helmet plugin because it is optional:

In Next it’s not optional, so users use import Head from 'next/head'. I don’t know if it is using react-helmet internally: https://github.com/zeit/next.js/#populating-head

import Head from 'next/head'

function IndexPage() {
  return (
    <div>
      <Head>
        <title>My page title</title>
        <meta name="viewport" content="initial-scale=1.0, width=device-width" />
      </Head>
      <p>Hello world!</p>
    </div>
  )
}

export default IndexPage

So there are examples of both. I think our case is more similar to Next because users can’t decide what library to use.

Following the conversation here.

If we are going to use things like @frontity/types/packages or @frontity/api/analytics I think we can use @frontity for everything. For example:

// instead of
import { Helmet } from 'react-helmet' 
// or
import Head from 'frontity/head' 
// use
import Head from '@frontity/head' 

and so on

// instead of
import { css } from '@emotion/core' 
import { styled } from '@emotion/styled' 
// use
import { css, styled } from '@frontity/css'
// instead of
import { Slot, Fill } from 'react-slot-fill' 
// use
import { Slot, Fill } from '@frontity/slot-fill' 

We keep the frontity package for the CLI only.

We need to decide this.

My last proposal is: use frontity for everything! :laughing:

Why? Because it’s easier to remember. Two ways:

  1. Direct imports:
import Head from 'frontity/head' 
import css from 'frontity/css'
import styled from 'frontity/styled'
import dynamic from 'frontity/dynamic'
import connect from 'frontity/connect'
import Slot from 'frontity/slot'
import Fill from 'frontity/fill'
  1. Named imports from the root:
import { Head, css, styled, dynamic... } from 'frontity' 

That’s it.

2 Likes

I’m tempted to do it for types as well:

import Package from 'frontity/types/package' 
import Settings from 'frontity/types/settings' 
import Action from 'frontity/types/action' 
import Derived from 'frontity/types/derived' 

and

import { Package, Settings, Action... } from 'frontity/types' 

and

import Source from 'frontity/types/source'
import Router from 'frontity/types/router'
import Comments from 'frontity/types/comments'

And leave @frontity/... only for official themes and extensions.

2 Likes

I think it’s a good idea.

Indeed.

We need to maintain @frontity/types to avoid a circular dependency between frontity and @frontity/core.

But I will use frontity/types to export stuff from @frontity/types anyway.

As explained in the Typings and Versions topic, we cannot do

import Source from 'frontity/types/source'

because source needs it’s own version. So using its own package is mandatory:

import Source from '@frontity/source'

Besides that, we cannot do

import connect from 'frontity/connect'

without installing @frontity/connect in frontity as it was our idea.

So we either:

  1. Install all the packages in frontity.
  2. Use the org for everything and create packages for everything, like @frontity/styled.

@development-team: which one do you prefer?

I have to say, the packages we need are rather small (react-helmet, @frontity/connect, @emotion/core…). I think npx frontity would still be fast.

I don’t understand what you mean when you say we need to install @frontity/connect in frontity. Why? I mean, you’ll use npx frontity mostly with the create command and I don’t see where we need @frontity/connect.

If you were to run frontity dev or any of its sibling commands, you would already need to have installed @frontity/core and its dependencies.

It is related to the idea of using imports from frontity/... like this:

import Head from 'frontity/head' 
import css from 'frontity/css'
import styled from 'frontity/styled'
import dynamic from 'frontity/dynamic'
import connect from 'frontity/connect'
import Slot from 'frontity/slot'
import Fill from 'frontity/fill'

If we want to do this, the packages needs to be installed in frontity because Webpack needs static imports.

These are the options:

Option 1A:

import { Head, css, connect... } from 'frontity'
import { Package, Action } from 'frontity/types' 

// Packages 
dependencies: {
   "frontity": "^1.0.0"
}

Option 1B:

import { Head, css, connect... } from 'frontity'
import { Package, Action } from '@frontity/types' 

// Packages 
dependencies: {
   "frontity": "^1.0.0",
   "@frontity/types": "^1.0.0"
}

Option 1C:

import Head from 'frontity/head' 
import css from 'frontity/css'
import styled from 'frontity/styled'
import dynamic from 'frontity/dynamic'
import connect from 'frontity/connect'
import Slot from 'frontity/slot'
import Fill from 'frontity/fill'

import Package from 'frontity/types/package' 
import Action from 'frontity/types/action' 

// Packages 
dependencies: {
   "frontity": "^1.0.0"
}

Option 2:

import { Head, css, connect... } from "@frontity/core"
import { Package, Action } from '@frontity/types' 

// Packages
dependencies: {
   "@frontity/core": "^1.0.0",
   "@frontity/types": "^1.0.0",
}

Option 3:

import Head from '@frontity/head' 
import css from '@frontity/css'
import styled from '@frontity/styled'
import dynamic from '@frontity/dynamic'
import connect from '@frontity/connect'
import Slot from '@frontity/slot'
import Fill from '@frontity/fill'

import Package from '@frontity/types/package' 
import Action from '@frontity/types/action' 

// Packages
dependencies: {
   "@frontity/types": "^1.0.0",
   "@frontity/css": "^1.0.0",
   "@frontity/styled": "^1.0.0"
   ...
}

This is mandatory in any of the options:

import Source from "@frontity/source"

Vote!

  • 1A
  • 1B
  • 1C
  • 2
  • 3

0 voters