Skip to main content

build with webpack and rollup

アプリにはcss等のファイルが扱えるwebpack, ライブラリには一つのファイルに縮小して変換してくれるrollupが使いやすいです。 特にcreate-react-appでReact環境を作成後、デモページの作成と同時にライブラリを開発するのが安定しているのでおすすめです。 今回は、cross-envでグローバル変数を設定し、react-app-rewiredcreate-react-appの中の設定を変更します. tsやcssなど追加で用いる場合はrollup/plugins: 🍣からプラグインを選んで使います。

  • create-react-app {yourapp} and cd {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に変更する。appSrcsrcから.にすると、srcdocsの両方がつかえる。)

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.jsoninclude:[...]のフォルダを修正します.

{
"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"
},
~~省略~~
}

先程、scriptscompileで指定したファイルのconfig-rollup.jsを追加します. (jsonglslをつかうなど、場合によってライブラリをインポートし、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