Git Product home page Git Product logo

react4xp-build-components's Introduction

react4xp-build-components

React4xp helper: basic webpack compilation of user-added React components in a React4xp structure

Webpack config script for compiling user-added React JSX components in an Enonic XP project.

Babel support because ES6, and React of course. It's possible to go beyond that and adjust or fine-tune this build step for your own needs.

Jump to:

Install

npm add --save-dev react4xp-build-components

Usage

webpack --config node_modules/react4xp-build-components/webpack.config.js --env.REACT4XP_CONFIG_FILE=/me/myproject/build/react4xpConfig.json

...where react4xpConfig.json is a JSON file containing React4xp setup constants - see below.

Quick overview

Running webpack like this, it will read your constants file (react4xpConfig.json in the example above) to see how the project's files and folders are structured.

It looks for JSX files, either among your XP components folders (pages and parts), OR outside the XP structure (in a folder pointed to by the constant SRC_R4X_ENTRIES - <rootDir>/src/main/resources/react4xp/_entries by default). These first-level JSX files are called Entries below.

The entries can import from other second-level JS/ES6/JSX files as usual.

  • Anything that's imported from node_modules in your project, will be compiled into a separate vendors chunk.

  • Anything that's imported from subfolders below SRC_R4X (default: <rootDir>/src/main/resources/react4xp), is compiled into chunks with the same name as the subfolder.

  • Everything else is compiled into separate files, by the same name as each found Entry JSX file.

Everything's compiled into a target build folder (BUILD_R4X - <rootDir>/build/resources/main/assets/react4xp by default), ready to be consumed by the React4xp runtime. In addition, the process creates a couple of JSON files, to guide the Runtime with dynamic filenames.

Structure

Constants

Use the Webpack env parameter REACT4XP_CONFIG_FILE to tell React4xp where to find a mandatory React4xp constants file. Full name and path are required. You can use react4xp-buildconstants to easily create a constants file.

Input

Looks for, and handles, React component that you add to the project sourcecode structure. These components are of three types, depending on where you put them:

1: React components bound to XP components:

JSX files inside the Enonic XP file structure, in the same folder as an XP component that uses them. Called from the XP component's controller JS, and inserted into the component's view HTML - the React4xp runtime makes this very easy. Supported XP component types are currently pages and parts. Layouts might work, but this is not well tested so YMMV.

React4xp needs to know the root of the Enonic XP structure: where to look for these JSX files. This is set with the SRC_SITE constant, usually: <rootDir>/src/main/resources/site.

Note that in order to avoid name collisions with XP's controller JS files, the React component files must have a '.jsx' file name extension. So obviously, other files in the structure must not, and you should avoid targeting the React4xp JSX files in other compile steps, for example if your XP controllers are ES6 files that need to be compiled.

This type of component is an Entry JSX file, and must export as default a function with a props argument (exporting pure HTML element in JSX works too) that returns a standard React component - for example:

// site/parts/example/example.jsx:

import React from 'react';
import WorldGreeter from "/path/to/WorldGreeter"

export default (props) => <WorldGreeter {...props} />;

2: Unbound components:

Callable JSX files put below a particular, designated source folder in your project. The source folder is controlled by the SRC_R4X_ENTRIES constant. Default value is <rootDir>/src/main/resources/react4xp/_entries. The _entries subfolder name can be specifically controlled with the R4X_ENTRY_SUBFOLDER constant.

Entries put in this special folder will be available to the React4xp runtime from anywhere, for client-side and/or server-side rendering.

Also an Entry type, so the same rules apply to the files here too: use '.jsx' file extension and expose a props -> component function from default (see the example above).

3: Shared components:

JSX files used by the entry components: the entries import shared components. During compilation the shared components are packed into component chunks: runtime libraries that contain everything the entries need.

Shared component source files are put below the main React4xp source folder in your project source, also controllable by a constant you can set: SRC_R4X (default: <rootDir>/src/main/resources/react4xp). Put shared components in subfolders below that - this will put them into optimized chunks with the same name as the subfolder. Just avoid the special folder pointed to by R4X_ENTRY_SUBFOLDER, which is only used for entries.

Note that source files that aren't imported by entries will not be compiled to the build folder at all. And if you add source files right on the root of <rootDir>/src/main/resources/react4xp/ (or wherever SRC_R4X points), they will be bundled into the entry files that use them, instead of a chunk - increasing the entry's size!

The shared-component syntax is just regular React: a JSX file that exports as default either a React stateless function component (a props -> component function)...

import React from 'react';

const WorldGreeter = (props) => <p>Hello {props.greetee}!</p>;

export default WorldGreeter;

...or as a stateful class component, for example:

import React from 'react';

class WorldGreeter expands React.Component {
    constructor(props) {
        this.state = {
            greetee: props || "world",
        }
    }
    
    render() {
        return (<p>Hello {this.state.greetee}!</p>);
    }
}

export default (props) => <WorldGreeter {...props} />;

Output

Compiles everything into a designated React4xp output folder, controllable by the BUILD_R4X constant (default: <rootDir>/build/resources/main/assets/react4xp):

  • Component entry files
  • Shared dependency chunks for components and vendors libraries
  • A JSON data file, chunks.json, that contains the file names of all the components and chunks (necessary for the runtime to know the built hashed names),
  • entries.json that contains the runtime names of all the compiled entry components (lets the runtime know what are the dependencies. Also useful for developers to see what components are available in runtime)

Using the entries

React4xp Entries are a common word for the components below the folders SRC_SITE and SRC_R4X_ENTRIES. They are runtime-callable part of a component: JS files that are a React "app" of their own, a top-level React component. These are what will be fed into the React4xp runtime renderer.

Since the dependency chunks are more optimized for re-use, the ideal use of entries are simply as triggers/containers, minimal wrappers that just import the actual components from the library chunks.

Each entry component has a name in runtime, or rather an entry path (called jsxPath in code). This name is defined by the file path of the JSX file, relative to the source folders (<rootDir>/src/main/resources/site or <rootDir>/src/main/resources/react4xp/_entries, or rather: wherever SRC_SITE and SRC_R4X_ENTRIES are pointing). It's also the path to the compiled files under <rootDir>/build/resources/main/assets/react4xp (or actually BUILD_R4X).

Running the entry files and chunks in runtime, makes the components callable under a global object called React4xp (can be controlled with the constant LIBRARY_NAME). The entry name is also used for fetching the component code in runtime, exposed by the React4xp runtime service, which looks for the compiled file under BUILD_R4X.

For example:

  • <rootDir>/src/main/resources/react4xp/_entries / Example.jsx will be compiled to <rootDir>/build/resources/main/assets/react4xp/Example.js and has the name Example. It can be called in runtime as React4xp.Example().
  • <rootDir>/src/main/resources/site / parts/example/example/example2.jsx is compiled to <rootDir>/build/resources/main/assets/react4xp/site / parts/example/example/example2.jsx has the entry name site/parts/example/example2, and is called as React4xp['site/parts/example/example2']()
  • ...etc...

More on code splitting

Like other shared and heavily re-used libraries in the React4xp structure, the chunks are optimized for being shared across multiple components pages, downloaded once and cached in the client, and reused when revisiting a page. Therefore, the chunks are content-hased for effective HTTP client caching and cache busting. This is handled entirely by the React4xp runtime out of the box. The react4xp-build-components build process produces JSON files with the hashed file names, used by the runtime for reference. This way, the compiled output is layered by code splitting. Third-party dependencies in node_modules are split out to a separate chunk: vendors.<HASH>.js. You can use the names of subfolders below the SRC_R4X folder (see the constants) to control which dependencies go in which chunk.

Currently, there is no dependency specificity detected in the build. So the runtime libs won't know which dependency chunks are needed from any one entry. This means all the dependency chunks are downloaded when an entry is needed. However, with successful HTTP client caching, this should only very rarely be noticeable after the first time.

Externals

If you set the EXTERNALS constant object, it will be used as the externals value in this webpack config script. You can use the same config file with the react4xp-runtime-externals helper, which will then build those libraries the same way as other dependencies but in a chunk of their own, nicely handled by the React4xp runtime. This allows them to function as regular webpack externals in the client, AND be used as dependencies for the react4xp runtime. This is also a different, easy way to insert additional dependency libraries that are needed both in client- and server-side runtime.

Supported syntax is as a straight object in the config JSON file, for example in react4xpConfig.json:

{ 
  ...

  "EXTERNALS": {
    "react": "React",
    "react-dom": "ReactDOM",
    "library-name": "ReferenceInCode"    
  },
  
  ...
}

Note that libraries declared as externals like this will not be available to the server-side runtime unless you use the react4xp-runtime-externals helper.

More about webpack externals

Adjusting this build step

This config only handles fairly basic React/ES6 compilation. It's pretty likely that you will need to fine-tune this setup for your own needs. You're encouraged to copy and expand the webpack.config.js from here as a template - especially the module.rules section can be useful to change.

If you do, it's recommended you still use a config file for React4XP as described below, and keep the steps using react4xp-build-entriesandchunks and chunks-2-json-webpack-plugin. They detect the added React component files and build the entry overview, normalize the structure into what the other React4xp steps expect, especially the runtime, and make sure everything fits together.

react4xp-build-components's People

Contributors

espen42 avatar realmunk avatar

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.