build with webpack and rollup
アプリにはcss等のファイルが扱えるwebpack
, ライブラリには一つのファイルに縮小して変換してくれるrollup
が使いやすいです。
特にcreate-react-app
でReact環境を作成後、デモページの作成と同時にライブラリを開発するのが安定しているのでおすすめです。
今回は、cross-env
でグローバル変数を設定し、react-app-rewired
でcreate-react-app
の中の設定を変更します.
tsやcssなど追加で用いる場合はrollup/plugins: 🍣からプラグインを選んで使います。
create-react-app {yourapp}
andcd {yourapp}
npm i -D cross-env react-app-rewired rollup @rollup/plugin-babel @rollup/plugin-node-resolve @rollup/plugin-commonjs fs
REF
次にconfig-overrides.js
ファイルを追加します。(ウェブページをsrc
からdocs
に変更する。appSrc
をsrc
から.
にすると、src
とdocs
の両方がつかえる。)
const fs = require('fs');
const path = require('path');
const appDirectory = fs.realpathSync(process.cwd());
const resolveApp = relativePath => path.resolve(appDirectory, relativePath);
module.exports = {
paths: function(paths, env) {
paths.appSrc = resolveApp('.');
paths.appIndexJs = resolveApp('docs/index.js');
// Typescript の場合
// paths.appTypeDeclarations = resolveApp('docs/react-app-env.d.ts');
return paths;
}
}
次にpackage.json
を修正します。(ライブラリのコンパイルにはrollup
を用い、他はreact-app-rewired
を使う。)Typescriptの場合は、tsconfig.json
のinclude:[...]
のフォルダを修正します.
{
"module": "index.js",
"types": "index.d.ts",
"main": "index.cjs.js",
"private": false,
"scripts": {
"test":"react-app-rewired test",
"eject":"react-app-rewired eject",
"start":"cross-env NODE_ENV=development BABEL_ENV=development react-app-rewired start",
"build":"cross-env NODE_ENV=production BABEL_ENV=production react-app-rewired build",
"compile":"cross-env NODE_ENV=production BABEL_ENV=production rollup -c config-rollup.js"
},
~~省略~~
}
先程、scripts
のcompile
で指定したファイルのconfig-rollup.js
を追加します.
(json
やglsl
をつかうなど、場合によってライブラリをインポートし、plugins
に追加していく)
import { promises as fs } from 'fs';
import babel from '@rollup/plugin-babel';
import resolve from '@rollup/plugin-node-resolve';
import commonjs from '@rollup/plugin-commonjs';
import pkg from './package.json';
const input = 'src/index'
const external = Object.keys({...pkg.dependencies,...pkg.devDependencies})
const extensions = ['.js', '.jsx', '.ts', '.tsx']
function babelOption (useESModules) {
return {
babelrc:false,
babelHelpers:'runtime',
exclude:'**/node_modules/**',
extensions,
presets : [
['@babel/env', {loose:true, modules:false}],
'@babel/preset-react','@babel/preset-typescript'
],
plugins : [
[ '@babel/proposal-class-properties' , {loose:true} ],
[ '@babel/plugin-proposal-object-rest-spread', {loose:true} ],
[ '@babel/transform-runtime', {regenerator:false,useESModules} ],
],
}
}
function targetTypings(out) {
return {
writeBundle () {
return fs.lstat(pkg.types).catch(() => {
return fs.writeFile(pkg.types, `export * from "./${input}"`)
})
}
}
}
export default [
{ input, output:{file:pkg.main ,format:'cjs'}, external, plugins:[
babel( babelOption(true) ),
commonjs({extensions}),
resolve ({extensions}),
targetTypings(),
]},
{ input, output:{file:pkg.module ,format:'esm'}, external, plugins:[
babel( babelOption(false) ),
commonjs({extensions}),
resolve ({extensions}),
targetTypings(),
] },
]
npm publish
- デモページができたら、
npm run build
- ライブラリができたら、
npm run compile
.npmignore
を作成し, rollupで作成したファイルとREADME.md以外を指定する.npm publish
で公開
.git
.gitignore
build
docs
node_modules
public
scripts