Skip to content
This repository has been archived by the owner on Apr 18, 2023. It is now read-only.

Add concrete example #4

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -59,3 +59,5 @@ typings/

# next.js build output
.next

dist
5 changes: 5 additions & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
**/scripts/**
**/dist/**
**/build/**
**/node_modules/**
**/.git/**
9 changes: 9 additions & 0 deletions .prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"singleQuote": true,
"printWidth": 80,
"jsxSingleQuote": false,
"bracketSpacing": true,
"arrowParens": "avoid",
"jsxBracketSameLine": true,
"semi": true
}
44 changes: 40 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,51 @@

This is an example repo of building plugins.

Here we've called the Stencil component library being wrapped `component-library` and the name of this React wrapper library `component-library-react`.

## Step 1.

- Update the `package.json` to have the correct package name for this repo.
- Replace `component-library` under `dependencies` with your core stencil package name.
- Update all occurrences of `component-library-react` with your chosen project name, say `my-library-react`.
- Update all occurrences of `component-library` with the name of the Stencil library you are wrapping, say `my-library`.
- Change the repository url in `package.json` to your own.

## Step 2.

- Build your core stencil package.
- Update `src/component/proxies.ts` with your Stencil component definitions, using the corresponding Ionic source as reference: `https://github.com/ionic-team/ionic/blob/master/packages/react/src/components/proxies.ts`

> TODO: This should really be automatically generated.

## Step 3.

- Run build on this package.
- Update the `package.json` version and `npm i`, `npm run build`, `npm publish`
- Update the dependecy version in the test app: `test/test-app` and run in the usual way


# End-to-end example

> The steps below depend on the following PR to be merged: https://github.com/ionic-team/stencil-component-starter/pull/83

1. Install verdaccio to create a quick local npm registry

- Install: `npm install --global verdaccio`
- Run in the terminal: `verdaccio`
- Set npm registry: `npm set registry http://localhost:4873/`
- Add a user: `npm adduser --registry http://localhost:4873`

2. Create and publich a new Stencil component library

- Create: `npm init stencil` (choose `component` and name it `component-library`)
- Change directory: `cd component-library`, install `npm i` and build `npm run build`
- Publish: `npm publish --registry http://localhost:4873`

3. Create and publish a React wrapper libary for the one above

- Clone: `git clone https://github.com/ionic-team/stencil-ds-react-template.git`
- Leave the defaults in place and cd `cd stencil-ds-react-template`, install `npm i` and build `npm run build`
- Publish: `npm publish --registry http://localhost:4873`

4. Run the React test app

- `cd test/test-app`, `npm i`, `npm start`

Presto!
14 changes: 0 additions & 14 deletions package-lock.json

This file was deleted.

92 changes: 61 additions & 31 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,54 +1,84 @@
{
"name": "component-library-react",
"sideEffects": false,
"version": "0.0.1",
"private": true,
"description": "React specific wrapper for component-library",
"keywords": [
"stencil",
"framework",
"react",
"mobile",
"app",
"hybrid",
"webapp",
"cordova",
"progressive web app",
"pwa"
],
"license": "MIT",
"repository": {
"type": "git",
"url": "https://github.com/ionic-team/ionic.git"
"url": "https://github.com/ionic-team/stencil-ds-react-template.git"
},
"scripts": {
"build": "npm run clean && npm run compile && npm run rollup",
"clean": "rm -rf dist",
"compile": "npm run tsc",
"build": "npm run clean && npm run copy && npm run compile",
"clean": "rm -rf dist && rm -rf dist-transpiled",
"compile": "npm run tsc && rollup -c",
"release": "np --any-branch --yolo --no-release-draft",
"lint": "tslint --project .",
"lint.fix": "tslint --project . --fix",
"tsc": "tsc -p .",
"rollup": "rollup -c"
"copy": "node scripts/copy.js",
"test.treeshake": "node scripts/treeshaking.js dist/index.esm.js"
},
"main": "./dist/index.cjs.js",
"module": "./dist/index.es.js",
"types": "./dist/index.d.ts",
"main": "dist/index.js",
"module": "dist/index.esm.js",
"types": "dist/types/index.d.ts",
"files": [
"dist/"
"dist/",
"css/"
],
"devDependencies": {
"@ionic-enterprise/react-component-lib": "0.0.1",
"@types/jest": "23.3.9",
"@types/node": "10.12.9",
"@types/react": "16.7.6",
"@types/react-dom": "16.0.9",
"jest": "^23.0.0",
"jest-dom": "^3.0.2",
"np": "^3.1.0",
"react": "^16.7.0",
"react-dom": "^16.7.0",
"rollup": "^1.21.2",
"rollup-plugin-node-resolve": "^5.2.0",
"typescript": "^3.3.4000"
},
"dependencies": {
"component-library": "^0.0.1"
"component-library": "0.0.1",
"tslib": "*"
},
"peerDependencies": {
"react": "^16.7.0",
"react-dom": "^16.7.0"
"react": "^16.8.6",
"react-dom": "^16.8.6"
},
"devDependencies": {
"@types/jest": "^23.3.9",
"@types/node": "10.12.9",
"@types/react": "^16.9.2",
"@types/react-dom": "^16.9.0",
"fs-extra": "^8.1.0",
"jest": "^24.8.0",
"jest-dom": "^3.4.0",
"np": "^5.0.1",
"react": "^16.9.0",
"react-dom": "^16.9.0",
"react-testing-library": "^7.0.0",
"rollup": "^1.18.0",
"rollup-plugin-node-resolve": "^5.2.0",
"rollup-plugin-sourcemaps": "^0.4.2",
"rollup-plugin-virtual": "^1.0.1",
"ts-jest": "^24.0.2",
"tslint": "^5.18.0",
"tslint-ionic-rules": "0.0.21",
"tslint-react": "^4.0.0"
},
"jest": {
"preset": "ts-jest",
"setupTestFrameworkScriptFile": "<rootDir>/jest.setup.js",
"setupFilesAfterEnv": [
"<rootDir>/jest.setup.js"
],
"testPathIgnorePatterns": [
"node_modules",
"dist"
"dist-transpiled",
"dist",
"test-app"
],
"modulePaths": [
"<rootDir>"
]
}
}
24 changes: 12 additions & 12 deletions rollup.config.js
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
import pkg from './package.json';
import resolve from 'rollup-plugin-node-resolve';
import sourcemaps from 'rollup-plugin-sourcemaps';

export default {
input: 'dist/index.js',

external: ['component-library', 'component-library/loader', 'react', 'react-dom'],

plugins: [resolve()],

input: 'dist-transpiled/index.js',
output: [
{
format: 'cjs',
file: pkg.main
file: 'dist/index.esm.js',
format: 'es',
sourcemap: true
},
{
format: 'es',
file: pkg.module
file: 'dist/index.js',
format: 'commonjs',
preferConst: true,
sourcemap: true
}
]
],
external: id => !/^(\.|\/)/.test(id),
plugins: [resolve(), sourcemaps()]
};
22 changes: 22 additions & 0 deletions scripts/copy.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
const fs = require("fs-extra");
const path = require("path");

function copyCSS() {
const src = path.join(__dirname, "..", "node_modules", "component-library", "css");
const dst = path.join(__dirname, "..", "css");

if (fs.existsSync(dst)) {
fs.removeSync(dst);
}
if (fs.existsSync(src)) {
fs.copySync(src, dst);
} else {
fs.mkdirSync(dst);
}
}

function main() {
copyCSS();
}

main();
96 changes: 96 additions & 0 deletions scripts/treeshaking.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@

const path = require('path');
const { rollup } = require('rollup');
const virtual = require('rollup-plugin-virtual');
const fs = require('fs');

function main() {
const input = process.argv[2] || get_input();
check(input).then(result => {
const relative = path.relative(process.cwd(), input);

if (result.shaken) {
console.error(`Success! ${relative} is fully tree-shakeable`);
} else {
error(`Failed to tree-shake ${relative}`);
}
});
}


function error(msg) {
console.error(msg);
process.exit(1);
}

function get_input() {
if (!fs.existsSync('package.json')) {
error(`Could not find package.json`);
}

const pkg = JSON.parse(fs.readFileSync('package.json'), 'utf-8');

const unresolved = pkg.module || pkg.main || 'index';
const resolved = resolve(unresolved);

if (!resolved) {
error(`Could not resolve entry point`);
}

return resolved;
}

function resolve(file) {
if (is_directory(file)) {
return if_exists(`${file}/index.mjs`) || if_exists(`${file}/index.js`);
}

return if_exists(file) || if_exists(`${file}.mjs`) || if_exists(`${file}.js`);
}

function is_directory(file) {
try {
const stats = fs.statSync(file);
return stats.isDirectory();
} catch (err) {
return false;
}
}

function if_exists(file) {
return fs.existsSync(file) ? file : null;
}

const check = input => {
const resolved = path.resolve(input);

return rollup({
input: '__agadoo__',
plugins: [
virtual({
__agadoo__: `import ${JSON.stringify(resolved)}`
}),
{
resolveId(id) {
if (!id.startsWith('.') && !id.startsWith('/')) {
return {id: id, external: true, moduleSideEffects: false};
}
return null;
}
}
],
onwarn: (warning, handle) => {
if (warning.code !== 'EMPTY_BUNDLE') handle(warning);
}
}).then(bundle => bundle.generate({
format: 'es'
})).then(o => {
const output = o.output;
console.log(output);
return {
shaken: output.length === 1 && output[0].code.trim() === ''
};
});
};

main();
4 changes: 4 additions & 0 deletions src/components/ReactProps.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@

export interface ReactProps {
className?: string;
}
Loading