Repository: lukejacksonn/es-react
Branch: master
Commit: c450874b4133
Files: 20
Total size: 12.7 KB
Directory structure:
gitextract_83v9dola/
├── .gitignore
├── .npmignore
├── README.md
├── index.d.ts
├── index.html
├── package.json
├── prop-types.d.ts
├── react-dom.d.ts
├── react-is.d.ts
├── react.d.ts
├── scripts/
│ ├── expand-exports-plugin.js
│ ├── replace-object-assign.js
│ ├── rollup.config.js
│ └── write-dev-pkgjson.js
└── src/
├── index.js
├── prop-types.js
├── react-dom-server-browser.js
├── react-dom.js
├── react-is.js
└── react.js
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitignore
================================================
node_modules
/dev
/*.js
================================================
FILE: .npmignore
================================================
/*
!dev/*.js
!dev/package.json
!*.js
!README.md
!package.json
================================================
FILE: README.md
================================================
# es-react
> An ES6 module exposing the latest version of react, react-dom, react-is, and prop-types
Ever wanted to just import react into your project as a module **without** a build step or even script tags? Native browser support for module [imports](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import) is [pretty good](https://caniuse.com/#feat=es6-module) so this should be an option for react developers now! Alas, there has not been an ES6 module compatible build released yet.
This package allows you import `react` and `react-dom` as ES6 modules from a CDN like [`unpkg`](https://unpkg.com):
```html
```
By default es-react exports the **production build** of react. For the **development build** use the `/dev` subfolder:
```js
import { React, ReactDOM } from 'https://unpkg.com/es-react/dev';
```
You may also import any members of the React package directly:
```js
import React, {
Component,
useState /* ... */,
} from 'https://unpkg.com/es-react';
```
And every package is also being provided as a separate file:
- `es-react/index.js`: Exports all of `React` and exports `{ React, ReactDOM, ReactIs, PropTypes }`
- `es-react/react.js`: Exports all of `React` plus a default export
- `es-react/react-dom.js`: Exports all of `ReactDOM` plus a default export (but not `react-dom/server`)
- `es-react/react-is.js`: Exports all of `ReactIs` plus a default export
- `es-react/prop-types.js`: Exports all of `PropTypes` plus a default export
- `es-react/react-dom-server.js`: Exports all of `ReactDOMServerBrowser` plus a default export
All development-versions of these packages are also available under `es-react/dev/`.
## Features
- All the latest React features (hooks, suspense, lazy, memo etc.)
- Use React directly from any javascript file (no build step required)
- Compatible with [`htm`](https://github.com/developit/htm) (for JSX compilation at runtime)
## Usage
Import `React` and `ReactDOM` directly from any script with `type="module"`. The package is intended to be available from [`unpkg`](https://unpkg.com) (without having to append `?module` to the package name).
```js
import { React, ReactDOM } from 'https://unpkg.com/es-react@16.13.1';
```
It is strongly advised that you specify a version when requesting the module – this speeds up the request time and helps with caching. If you don't specify a number then unpkg will redirect and serve up the latest available version.
## Example
Create a new file, copy the code below into it and then open the file in a browser – or [try online](https://codepen.io/lukejacksonn/pen/EMxVWM).
> If you would like the browser to reload when you update the code, then you can use a dev server like [servor](https://github.com/lukejacksonn/servor) dependency free by running `npx servor --reload --browse`.
```js
```
## Implementation
The latest versions of all packages are installed via (pinned) entries in `package.json` and built and bundled using Rollup with automatic code splitting.
The exports of each package are automatically expanded and `object-assign` is stripped from the output, since all browsers that support ESM will also support `Object.assign`
(See `scripts/expand-exports-plugin.js` and `scripts/replace-object-assign.js` for the Babel plugins that do this)
## Acknowledgements
Barely any of the code in this repo is written by myself. It is just a wrapper for React that is written and maintained by the team at Facebook. Thanks to my employer [Formidable](https://github.com/formidablelabs) for allowing me the time to think about and work on fun and experimental projects like this.
================================================
FILE: index.d.ts
================================================
import * as React from './react';
import * as ReactDOM from './react-dom';
import * as PropTypes from './prop-types';
export { React, ReactDOM, PropTypes };
export * from './react';
export default React;
================================================
FILE: index.html
================================================
================================================
FILE: package.json
================================================
{
"name": "es-react",
"version": "16.13.1",
"description": "An ES6 module exposing the latest version of react and react-dom",
"module": "index.js",
"types": "index.d.ts",
"keywords": [
"react",
"es",
"module",
"import",
"export"
],
"repository": "https://www.github.com/lukejacksonn/es-react",
"bugs": {
"url": "https://github.com/lukejacksonn/es-react/issues"
},
"scripts": {
"build": "rollup -c scripts/rollup.config.js",
"clean": "rimraf *.js dev",
"prepare-dev": "node ./scripts/write-dev-pkgjson.js",
"prepublishOnly": "run-s clean build prepare-dev"
},
"author": "@lukejacksonn",
"license": "MIT",
"devDependencies": {
"@babel/core": "^7.6.2",
"npm-run-all": "^4.1.5",
"prop-types": "15.7.2",
"react": "16.13.1",
"react-dom": "16.13.1",
"react-is": "16.13.1",
"rimraf": "^3.0.0",
"rollup": "^1.21.4",
"rollup-plugin-babel": "^4.3.3",
"rollup-plugin-commonjs": "^10.1.0",
"rollup-plugin-node-resolve": "^5.2.0",
"rollup-plugin-replace": "^2.2.0"
},
"dependencies": {
"@types/prop-types": "^15.7.3",
"@types/react": "^16.9.19",
"@types/react-dom": "^16.9.5",
"@types/react-is": "^16.7.1"
}
}
================================================
FILE: prop-types.d.ts
================================================
export * from 'prop-types';
================================================
FILE: react-dom.d.ts
================================================
export * from 'react-dom';
================================================
FILE: react-is.d.ts
================================================
export * from 'react-is';
================================================
FILE: react.d.ts
================================================
export {
Children,
Component,
Fragment,
Profiler,
PureComponent,
StrictMode,
Suspense,
cloneElement,
createContext,
createElement,
createFactory,
createRef,
forwardRef,
isValidElement,
lazy,
memo,
useCallback,
useContext,
useDebugValue,
useEffect,
useImperativeHandle,
useLayoutEffect,
useMemo,
useReducer,
useRef,
useState,
version
} from 'react';
================================================
FILE: scripts/expand-exports-plugin.js
================================================
const toIdentifierName = str => str.replace(/[^\w]+/g, '');
/** expand-exports-plugin for Babel
* This plugin expands exports for CommonJS modules into granular
* export-default and export-all declarations.
*
* It takes a "map" option that must be an object from
* module names (e.g. 'react') to filenames.
* It then replaces export-all declarations (i.e. "export *") with
* granular exports that export all named keys and a default export.
*/
const expandExportsPlugin = ({ template, types: t }) => ({
visitor: {
ExportAllDeclaration(path, state) {
const { map } = state.opts;
const module = path.node.source.value;
const file = map[module];
// We retrieve the module name and filename from the map
if (typeof file === 'string') {
// We turn the module name to a safe identifier
const importId = t.identifier(toIdentifierName(module));
// We retrieve all exports via CommonJS in Node
const exportKeys = Object.keys(require(file));
// import %importId% from "%file%;
const importNode = t.importDeclaration(
[t.importDefaultSpecifier(importId)],
t.stringLiteral(file)
);
// export default %importId%;
const defaultExportNode = t.exportDefaultDeclaration(importId);
// export const { %exportKeys% } = %importId%;
const exportsNode = t.exportNamedDeclaration(
t.variableDeclaration(
'const',
[t.variableDeclarator(
t.objectPattern(
exportKeys.map(name => {
const identifier = t.identifier(name);
return t.objectProperty(
identifier,
identifier,
false,
true
);
})
),
importId
)]
),
[]
);
// Replace the export-all declaration with new nodes
path.replaceWithMultiple([
importNode,
defaultExportNode,
exportsNode
]);
}
}
}
});
export default expandExportsPlugin;
================================================
FILE: scripts/replace-object-assign.js
================================================
const replaceAssignPlugin = ({ types: t }) => ({
visitor: {
CallExpression(path, state) {
const { callee, arguments: args } = path.node;
if (
t.isIdentifier(callee) &&
callee.name === 'require' &&
t.isStringLiteral(args[0]) &&
args[0].value === 'object-assign'
) {
path.replaceWithSourceString('Object.assign');
}
}
}
});
export default replaceAssignPlugin;
================================================
FILE: scripts/rollup.config.js
================================================
import commonjs from 'rollup-plugin-commonjs';
import nodeResolve from 'rollup-plugin-node-resolve';
import babel from 'rollup-plugin-babel';
import replace from 'rollup-plugin-replace';
import expandExportsPlugin from './expand-exports-plugin';
import replaceAssignPlugin from './replace-object-assign';
const exportsMap = (isProduction = false) => ({
react: `react/cjs/react.${isProduction ? 'production.min' : 'development'}.js`,
'react-is': `react-is/cjs/react-is.${isProduction ? 'production.min' : 'development'}.js`,
'react-dom': `react-dom/cjs/react-dom.${isProduction ? 'production.min' : 'development'}.js`,
'react-dom-server-browser': `react-dom/cjs/react-dom-server.browser.${isProduction ? 'production.min' : 'development'}.js`,
'prop-types': 'prop-types/index.js',
});
const config = (isProduction = false) => ({
input: {
index: './src/index.js',
react: './src/react.js',
'react-is': './src/react-is.js',
'react-dom': './src/react-dom.js',
'react-dom-server-browser': './src/react-dom-server-browser.js',
'prop-types': './src/prop-types.js'
},
plugins: [
babel({
babelrc: false,
plugins: [
// This expands all our exports
[expandExportsPlugin, {
map: exportsMap(isProduction)
}],
// This replaces object-assign with native Object.assign
replaceAssignPlugin
],
}),
nodeResolve({
mainFields: ['module', 'jsnext', 'main'],
browser: true,
}),
commonjs({
ignoreGlobal: true,
include: /\/node_modules\//,
namedExports: {
react: Object.keys(require('react')),
'react-is': Object.keys(require('react-is')),
'react-dom': Object.keys(require('react-dom')),
'react-dom-server-browser': Object.keys(require('react-dom/server.browser')),
'prop-types': Object.keys(require('prop-types')),
},
}),
replace({
'process.env.NODE_ENV': JSON.stringify(
isProduction ? 'production' : 'development'
)
})
],
onwarn: () => {},
treeshake: {
moduleSideEffects: false,
propertyReadSideEffects: false
}
});
export default [
{
...config(true),
output: {
compact: true,
interop: false,
freeze: false,
dir: './',
entryFileNames: '[name].js',
chunkFileNames: '[name]-[hash].js',
format: 'esm'
}
},
{
...config(false),
output: {
compact: true,
interop: false,
freeze: false,
dir: './dev',
entryFileNames: '[name].js',
chunkFileNames: '[name]-[hash].js',
format: 'esm'
}
}
];
================================================
FILE: scripts/write-dev-pkgjson.js
================================================
#!/usr/bin/env node
const fs = require('fs');
const path = require('path');
const dir = path.resolve(__dirname, '../dev');
if (!fs.existsSync(dir)) {
fs.mkdirSync(dir);
}
const pathToPkgJson = path.resolve(dir, 'package.json');
if (fs.existsSync(pathToPkgJson)) {
fs.unlinkSync(pathToPkgJson);
}
const mainPkgJson = require('../package.json');
const contents = JSON.stringify(
{
name: '@es-react/dev',
version: mainPkgJson.version,
license: mainPkgJson.license,
private: true,
module: 'index.js',
},
undefined,
2
);
fs.writeFileSync(pathToPkgJson, contents);
================================================
FILE: src/index.js
================================================
import React from './react';
import ReactDOM from './react-dom';
import ReactDOMServerBrowser from './react-dom';
import PropTypes from './prop-types';
export { React, ReactDOM, ReactDOMServerBrowser, PropTypes };
export * from './react';
export default React;
================================================
FILE: src/prop-types.js
================================================
export * from 'prop-types';
================================================
FILE: src/react-dom-server-browser.js
================================================
export { default } from 'react-dom/server.browser';
================================================
FILE: src/react-dom.js
================================================
export * from 'react-dom';
================================================
FILE: src/react-is.js
================================================
export * from 'react-is';
================================================
FILE: src/react.js
================================================
export * from 'react';