Giter Club home page Giter Club logo

formidable-playbook's Introduction

This is our playbook. It is the foundation that allows us to architect & design systems that move our client projects forward. In it, you will find practical approaches for building frontend & backend javascript applications. This is a living document, and we intend to share our knowledge as we continue to work towards making the web a better place.

The Architecture Playbook

A unified development effort should use a single infrastructure to control all similar projects.

The Frontend Playbook

Our frontend infrastructure is based around webpack builds, but most of the guidelines / goals apply to any build tool.

Webpack plugins

Webpack has a rich plugin ecosystem, including both core and open source modules. Webpack also has a straight forward interface to write your own plugins.

A short list of plugin recommendations for best frontend performance include:

Plugin Recommend? Notes
UglifyJsPlugin Yes Minimize code
DedupePlugin Yes for v1 Collapse identical code chunks to a single reference
OccurrenceOrderPlugin Maybe for v1 Reorder module and chunk ids by occurrence count
DefinePlugin Maybe Define constants for better optimization
lodash-webpack-plugin Maybe Optimize lodash

Code splitting is a Webpack feature that enables a JS bundle within a single build to be split up and loaded on-demand in smaller parts. Code splitting is appropriate within a single page and build.

Webpack shared libraries are slightly different from code splitting scenarios in that the common dependencies are shareable across builds and require a two-part build. In a first step, a common shared bundle and manifest is created. Then, in a second step, entry points ingest the manifest and omit any libraries included in the shared bundle. Shared libraries are appropriate for better long term caching within a single app across deploys and across different projects / real HTML pages.

Scope hoisted bundles try to place bundle modules into a global bundle scope so as to reduce the overhead of function calls for each bundled module. The problem and scope hoisting solutions are discussed in detail in Nolan Lawson's 2016 article "The cost of small modules"

Tree shaking is a transformation process for ES6 modules whereby ESnext exports that are not used in a Webpack bundle can be isolated during code bundling and removed entirely by Uglify dead code elimination.

The Webpack SourceMapDevToolPlugin creates source maps which allows a developer to view / debug developer-friendly source code instead of the optimized, mangled, and minified JS bundle of a frontend web app. Source maps should be enabled for both development and production.

Babel plugins - In Progress

Other tools - In Progress

Performance auditing - In Progress

The Backend Playbook - In Progress

formidable-playbook's People

Contributors

bmathews avatar coopy avatar ebrillhart avatar kylecesmat avatar paulathevalley avatar ryan-roemer avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

formidable-playbook's Issues

Feature: Ingest real code snippets into MD documents

Find or write a parser that does something like the following:

  • Parse MD documents looking for control comments like <!-- INSERT:../../examples/frontend/src/es5/app1.js --> (full source) or <!-- INSERT:../../examples/frontend/src/es5/app1.js:foo-comment -->
  • Then parse the linked source document to expand the full source or something between /* START:foo-comment */stuff/* END:foo-comment */
  • Insert current code as applicable back in MD docs.
  • Add a task to update code snippets as part of npm run build.

Build: Make windows compatible.

We've shortened the npm run build subcommands to be more terse using real bash. But this breaks windows builds.

Task: Make all npm script commands windows compatible.

Add Analytics

We should implement analytics using react-ga for this project

Create Mobile section

This here is an outline of a new top-level section for React Native mobile development.

Whereas the existing Frontend playbook content is heavily tooling-focused, I would like this document to also discuss concepts and patterns. React Native is in some ways an immature field and existing React best practices may not always apply, or it might not be clear how to apply them. The likelihood of a developer getting their very first React Native project is also rather high for the time being, and discussing basics and good practices add value.

Initial braindump, let's discuss and align practices with existing Formidable RN work and then revise structure and scope. Many of these topics are minor/contestable and might not be worth including in the playbook. Others might be too large and deserve to be a blog post or a library instead.

The Mobile Playbook

  • Platform-specific code iOS/Android
    • Prefer to separate *.ios.js and *.android.js component files over switching on Platform.*
    • Prefer to split UI into smaller components until lowest common denominator. If applicable, separate only styles into *.styles.ios.js and *.styles.android.js to avoid duplication of code
    • Prefer pure JS implementation over custom native components for maintainability
    • Prefer to wrap native platform UI components to achieve native look-and-feel over implementing from scratch
    • Managing native dependencies (npm vs Maven/CocoaPods/Carthage)
    • Patterns for authoring native modules
    • Follow platform design guidelines (Apple Human Interaction Guidelines, Google Material Design)
  • State management
    • Persist Redux/Flux store to disk to survive shutdowns and tombstoning
    • Prepare for store schema migrations/pruning on updates
    • Using GraphQL with Redux+Apollo vs Relay (discuss)
  • Navigation and routing
    • Storing navigation state in Redux/Flux store with NavigationExperimental (discuss)
    • Navigation UX patterns for iOS and Android
  • Quality assurance
    • Crashing issues in mobile apps are more serious than on web (worst case bricked app, not always easy to deploy hotfixes)
    • Use Flow to reduce errors (built into React Native)
    • Unit testing with Mocha+Enzyme or Jest snapshot testing (discuss)
    • UI testing automation with Calaba.sh and Xamarin Test Cloud
  • Networking
    • Always use timeouts
    • Only use HTTPS endpoints
    • Catch and rethrow async/await errors at call site (or just use Promises)
    • Backend API versioning and forced updates
    • Mobile app needs a mobile backend, consider BFF
  • Offline-resilient applications
    • Dealing with poor network conditions
    • Patterns for handling optimistic state updates, synchronization and errors
  • Authentication
    • Use JSON Web Tokens and token invalidation
    • Social authentication providers (OAuth, OpenID)
  • Performance
    • Common pitfalls: Large ListViews, animating while running interactions
    • Tools for optimising performance
  • Debugging
    • redux-remote-devtools
  • Deployments
    • Automate build and deployment with Fastlane
    • Continuous Integration (Options: Bitrise.io, Jenkins + Private Build Server, Microsoft VSTS + MacInCloud build agents) (discuss)
    • Continuous deployment with Microsoft Code Push
  • Beta and pre-release testing
    • Play Store Beta program / Apple TestFlight
    • Third party SDKs: HockeyApp / Crashlytics (discuss)
    • Configuring apps to support multiple environments
  • Running in production
    • App Store / Play Store submission process
    • Complying with App Store guidelines
    • Crash reporting
    • Behavioral analytics
    • Push notifications
    • A/B testing
  • Surviving React Native
    • Embrace the Hacker Way
    • Upgrade often, but not too early
    • Read the source

/cc @ryan-roemer @kenwheeler

Create Electron Section

This is kind of a brain-dump of the different Electron topics I'd like to see in the playbook.

Subsection proposals:

  • Constructing the Main process
  • Constructing Renderer processes
  • Working with Native UI
  • Build and Release Management (especially cross-platform)

Specific topics:

  • Inter-process communication (with recipes!)
  • Authentication
  • Using SQLite or other "persistent" storage

Create Optimization section

Meta:

  • Create outline
  • Generate list of applicable tools
  • Write section and refer to tools

Specifics

  • inspectpack basics
  • inspectpack action: sizes
  • inspectpack action: duplicates + versions
  • inspectpack action: parse + files + patterns
  • source-map-explorer

Remove TODO Headers from README

We should remove this TODO copy as it adds clutter to the home page in its current form. We will ensure that any notes for these todos are moved into issues.

Backend - Deploy: tar up bits on build server and drop on app servers.

draft suggestion


Why should I tar and deploy a single build for my project?

  • Guarantee a consistent node_modules tree across npm and git dependencies.
  • Have an auditable deployment artefact.
  • Dramatically speed up application deploys.
  • Allow quicker, easier rollback production scenarios.
  • Avoid "thundering herd" installation issues from a single repository.

Backend - Deploy: use `shrinkwrap`

draft suggestions


Why should I shrinkwrap my project?

Omitting a shrinkwrap creates enormous risk for any frontend or backend project that relies on npm install and node_modules. The core problem is that an npm install is likely to produce different results on different installs from the exact same root package.json file.

The first level of why this is the case lies in the fact that although a package.json might pin dependencies, it is extremely likely that the dependencies of those dependencies (and further down the dependency tree) will contain:

  • A semver minor/patch npm range dependency. Virtually guaranteed in any modern project.
  • A semver major npm dependency.
  • A wildcard "any latest" npm dependency. Not as likely, but possible.

The second level if that any git dependencies that are not hash-specific (either master or a tagged branch) can be updated at will.

Taking both of these considerations in mind, it becomes apparent that doing an npm install at "time number 1" can be different from "time number 2".

Now, let's consider three critical points in time of the development to production workflow:

  • Development time: In development, committing to master for a release. This is the cheapest time to discover bugs and fix them.
  • QA / integration test time: In qa built for integration testing in a CI server. This is the second cheapest time. You are not at production yet and won't have a customer-facing revenue impact.
  • Production time:Deploying the application on each application server. This is the most expensive time. Production has revenue impacts and pushing fixes through the development pipeline costs more in development resources.

If you don't have a shrinkwrap file, you are potentially deploying different packages for each of development, QA, and production time. This means that:

  • You have potentially never tested the code actually running in production.
  • Different production app servers can be running different code even from each other.
  • Your app is at risk to any semver-compliant / dependency-range-allowed bugs introduced in any package anywhere in your dependency tree.

Thus, by locking down a shrinkwrap file you guarantee that:

  • The development dependencies are the same as the QA and production dependencies. (Except git tags).
  • Each application server has the same dependencies. (Except git tags).

While there is a slight development cost to maintaining a shrinkwrap file in the development workflows, in practically all cases where "correctness" is important to a production-facing application, using a shrinkwrap will be a strongly recommendation production best practice.

References:

Shared Libs Clarification

In the webpack-shared-libs.md front-end documentation, there is note regarding cross-project sharing:

NOTE - Cross project sharing: The biggest thing to understand for shared libraries is that this first step can be completely independent of the second entry point build step -- across:

Multiple entry points in the same project / application
Multiple entry points in different projects / applications
This means that we have a truly portable, cacheable library for an entire website or collection of sites, unlike the project-specific code splitting solution.

But how can the shared library be used between completely different projects (i.e. a website composed of multiple front-end applications/components) when the manifest is created at runtime? How is manifest shared between different projects?

I know the shared library's bundle dist/js/lib.js can be shared if we set the output target to UMD but how do we achieve this when projects are in completely different repos/builds? Am I missing something in my understanding? Any clarification would be super appreciated!!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.