Closed17
gulpでtsを触る
これをgulpでやる
このパッケージを見つけた
多分ソース見る限り、throughで受け取ってからrenderToStaticMarkupして上げれば良い感じかな?
Q. なぜgulpでやるのか
A. 単純にwebpackを使う必要が無いから
css-loaderなどを使う必要が無いので多分gulpでやった方が良いとの判断
pageを増やす度にwebpackを止めないといけないけどめんどくさいgulpなら止めなくても大丈夫
今回使うリポジトリ
とりあえず、gulpが動くまで設定
最初の目標
src/pages/index.tsxをdist/index.tsxとして出力
- npmの初期設定をする
$ npm init -y
- いらないフィールドを消す
package.json
{
"name": "gulp-react-static-generate",
"version": "1.0.0",
"description": "",
"license": "MIT",
"author": "hisho",
"scripts": {
"start": "echo \"Error: no test specified\" && exit 1"
}
}
- src/pages/index.tsxを作成する
$ mkdir src && mkdir src/pages && touch src/pages/index.tsx
- gulp周りをインストールする
$ npm i -D gulp npm-run-all
- gulpのtaskを作成する
$ mkdir gulpfile.js && touch gulpfile.js/index.js && touch gulpfile.js/reactRenderStaticMarkup.js
- node.js周りをインストールする
$ npm i -D @types/node
- gulpの設定をする
gulpfile.js/reactRenderStaticMarkup.js
const gulp = require('gulp');
reactRenderStaticMarkup = (done) => {
gulp
.src('src/pages/**/*.tsx')
.pipe(gulp.dest('dist'))
done();
}
module.exports = reactRenderStaticMarkup;
gulpfile.js/index.js
const gulp = require('gulp');
const reactRenderStaticMarkup = require('./reactRenderStaticMarkup');
exports.renderReact = reactRenderStaticMarkup;
exports.watch = () => {
gulp.watch('src/pages/**/*.tsx', reactRenderStaticMarkup);
}
package.json
{
"name": "gulp-react-static-generate",
"version": "1.0.0",
"description": "",
"license": "MIT",
"author": "hisho",
"scripts": {
"start": "run-s gulp-render-react gulp-watch",
"build": "run-p gulp-render-react",
"gulp-render-react": "gulp renderReact",
"gulp-watch": "gulp watch"
},
"devDependencies": {
"@types/node": "^15.0.2",
"gulp": "^4.0.2",
"npm-run-all": "^4.1.5"
}
}
- LICENCEを作る
コマンドをREADME.mdに追記する
動作環境
- OS: macOS
- Node: v14.16.1
- npm: 7.9.0
コマンド
インストール
$ npm ci
ウォッチ
$ npm start
ビルド
$ npm run build
License
動作確認できたので一旦コミット
やるべきこと
- tsをトランスパイル
- throughで受け取りhtmlに変換
- 吐き出し
こんな感じかな?
まずはReactをインストールする
$ npm i react react-dom
typesを入れる
$ npx typesync
$ npm i
とりあえずtsxをjsxに変換する
$ npm i -D gulp-typescript typescript
$ touch tsconfig.json
tsconfig.json
{
"compilerOptions": {
"target": "esnext",
"lib": [
"dom",
"dom.iterable",
"esnext"
],
"allowJs": true,
"skipLibCheck": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"noEmit": true,
"esModuleInterop": true,
"module": "esnext",
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "preserve",
},
"include": [
"src/**/*.ts",
"src/**/*.tsx"
],
"exclude": [
"node_modules"
]
}
gulpfile.js/reactRenderStaticMarkup.js
const gulp = require('gulp');
const ts = require('gulp-typescript');
const path = require('path');
const tsProject = ts.createProject(path.resolve(process.cwd(),'tsconfig.json'));
reactRenderStaticMarkup = (done) => {
gulp
.src('src/pages/**/*.tsx')
.pipe(tsProject())
.pipe(gulp.dest('dist'))
done();
}
module.exports = reactRenderStaticMarkup;
$ npm run gulp-render-react
トランスパイル前
src/pages/index.tsx
import React from "react";
const IndexPage: React.VFC = () => {
return (
<div>
ハロー
</div>
)
}
トランスパイル後
dist/index.jsx
import React from "react";
const IndexPage = () => {
return (<div>
ハロー
</div>);
};
.tsx
からjsx
にした後の処理一番めんどくさそうなので先に.tsx
を.html
として出力する
$ npm i -D through2
$ npx typesync
$ npm i
gulpfile.js/reactRenderStaticMarkup.js
const gulp = require('gulp');
const ts = require('gulp-typescript');
const path = require('path');
const through = require("through2");
const gutil = require('gulp-util');
const tsProject = ts.createProject(path.resolve(process.cwd(), 'tsconfig.json'));
reactRenderStaticMarkup = (done) => {
gulp
.src('src/pages/**/*.tsx')
.pipe(tsProject())
.pipe(through.obj((file, _, callback) => {
//何かしらのプラグインがファイルの中身を stream にして次に渡して来た時
if (file.isStream()) {
callback(new gutil.PluginError('react render static', 'Streams not supported'));
return callback(null, file);
}
//ファイルの中身がBufferとしてわたってきた場合
if (file.isBuffer()) {
try {
//現在処理しているfileのpath
const modulePath = path.resolve(process.cwd(), file.path);
//現在処理しているfileのext(拡張子)
const moduleExt = path.extname(modulePath);
//拡張子を.htmlに変換する
file.path = file.path.replace(new RegExp(`${moduleExt}$`), '.html');
//変換後のfileを返す
return callback(null, file);
//エラーの処理
} catch (e) {
console.error("ERROR RENDERING TSX PAGE: ", e.stack);
return callback(null, file);
}
}
}))
.pipe(gulp.dest('dist'))
done();
}
module.exports = reactRenderStaticMarkup;
とりあえず、.tsx
を.html
に吐き出すのはできた
くそう詰んだ
元のプラグインではjsxをそのままnodeでimportしてReact.createElement()してReact.renderToStaticMarkup()をしているけど、tsxからだとそのパターンが使えない
くぅ〜1時間調べても進展が無いので諦めます😂
- tsx
- jsx
- React.ReactNodeを取得する
- renderToStaticMarkupで文字列に変換する
- 文字列をfile.contetnsに渡す
- 拡張子を.htmlに変換する
この手順で行けるはずなんだけど、React.ReactNodeを取得する
ができない
後、webpackと違って
import React from "react";
import {Layout} from "../layouts/Layout";
export default function () {
return (
<Layout>
<h1>タイトル</h1>
ハロー
</Layout>
)
}
これが
import React from "react";
import {Layout} from "../layouts/Layout";
export default function () {
return (
<div>
レイアウト
<h1>タイトル</h1>
ハロー
</div>
)
}
こうならない
このスクラップは2021/05/12にクローズされました