この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
SalesforceのVisualforce Componentの作成をReactを使って行ってみました。 Vue.jsやAngularなども同様の方法で使えると思います。
Salesforceの環境にDeveloper Edition組織を使っています。
Visualforce Page / Componentの骨組みを作る
VSCodeのコマンドパレットで[SFDX: Create Visualforce Page]を実行してVisualforce Pageの骨組みを作ります。 ここではページ名を[ReactSampleVFPage]にしました。
force-app/main/default/pages/ReactSampleVFPage.page*
が作成されました。
続いて、コマンドパレットで[SFDX: Create Visualforce Component]を実行してVisualforce Componentの骨組みを作ります。 ここではコンポーネント名を[ReactSampleVFComponent]にしました。
force-app/main/default/components/ReactSampleVFComponent.component*
が作成されました。
Hello, Worldを作ってデプロイする
force-app/main/default/pages/ReactSampleVFPage.page
を選択して、下記に変更します。
<apex:page>
<!-- Begin Default Content REMOVE THIS -->
<h1>Congratulations</h1>
<c:ReactSampleVFComponent />
<!-- End Default Content REMOVE THIS -->
</apex:page>
続いて、force-app/main/default/components/ReactSampleVFComponent.component
を選択して、下記に変更します。
<apex:component>
<!-- Begin Default Content REMOVE THIS -->
<h1>Congratulations</h1>
Hello, World.
<!-- End Default Content REMOVE THIS -->
</apex:component>
変更したら、force-app/main/default/
を選択した状態で[SFDX: Deploy Source to Org]を実行して、ReactSampleVFPageとReactSampleVFComponentを組織にデプロイします。
デプロイできたら組織にログインし、[設定] > [Visualforceページ] > [ReactSampleVFPage]に移動して、[Lightning Experience、Lightning コミュニティ、およびモバイルアプリケーションで利用可能]にチェックを入れます。
続いて任意のアプリケーション(ここでは[サービス]を選択)のホームに移動し、画面右上の歯車アイコンをクリックして[編集ページ]をクリックします。
左メニューのVisualforceをドラッグアンドドロップでページ内の任意の箇所に配置し、画面右の[Visualforceページ名]に[ReactSampleVFPage]を指定して保存します。
ホーム画面に「Hello, World」と表示されるようになることを確認します。
ReactでVisualforce Componentを作る
webpackで1ファイルにまとめたbundle.jsを作成し、index.htmlにてこのbundle.jsを読み込んでReactが動作するようにします。 手順は大筋で参考にさせていただいた「Babelとwebpackを使ってES6でReactを動かすまでのチュートリアル」の記事の通りですので、この記事では簡単に手順を示すに留めます。
下準備
$ mkdir react-sample
$ cd react-sample
$ git init
$ npm init -y
$ mkdir src dist
ここではプロジェクトディレクトリを[react-sample]としています。
babelとwebpackの設定
$ npm i -D @babel/core babel-loader @babel/preset-env @babel/preset-react @babel/register
$ cat > .babelrc
{
"presets": [
"@babel/preset-env", "@babel/preset-react"
]
}
$ npm i -D webpack webpack-cli
$ npm i -D webpack-dev-server html-webpack-plugin
$ cat > webpack.config.js
require('@babel/register');
module.exports = require('./development');
$ cat > development.js
import path from 'path'
import HtmlWebpackPlugin from 'html-webpack-plugin'
const src = path.resolve(__dirname, 'src')
const dist = path.resolve(__dirname, 'dist')
export default {
mode: 'development',
entry: src + '/index.jsx',
output: {
path: dist,
filename: 'bundle.js'
},
module: {
rules: [
{
test: /\.jsx$/,
exclude: /node_modules/,
loader: 'babel-loader'
}
]
},
resolve: {
extensions: ['.js', '.jsx']
},
plugins: [
new HtmlWebpackPlugin({
template: src + '/index.html',
filename: 'index.html'
})
]
}
Reactパッケージのインストール
$ npm i -S react react-dom
$ cat > src/index.jsx
import React from 'react';
import {render} from 'react-dom';
class App extends React.Component {
render () {
return <p> Hello React!</p>;
}
}
render(<App/>, document.getElementById('root'));
$cat > src/index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>React Test</title>
</head>
<body>
<div id="root"/>
</body>
</html>
動作確認
./node_modules/.bin/webpack-dev-server
上記コマンドでWebサーバを立ち上げ、http://localhost:8080/にアクセスします。 画面に「Hello, React!」と表示されることを確認します。
Visualforce ComponentにReactアプリケーションを組み込む
webpackを実行してbundle.js
とindex.html
を作成します。
$ ./node_modules/webpack/bin/webpack.js
$ ls dist
bundle.js index.html
Salesforceの静的リソースに登録するために、zipに固めます。
$ cd dist
$ zip ReactSample.zip bundle.js index.html
作成したzipファイルを静的リソースに設定します。
静的リソース名は[ReactSample]としました。
次にforce-app/main/default/pages/ReactSampleVFPage.page
を下記に変更します。
<apex:page showHeader="false" standardStylesheets="false" title="ReactSample" id="page">
<meta charset="utf-8"/>
<title>ReactSample Page</title>
<c:ReactSampleVFComponent />
<script src="{!URLFOR($Resource.ReactSample, 'bundle.js')}"></script>
</apex:page>
先に作成した静的リソースのbundle.jsを{!URLFOR($Resource.ReactSample, 'bundle.js')}
で参照しています。
<script>タグはコンポーネントの呼び出し(<c:ReactSampleVFComponent />
)より後にする必要がありますので注意してください。
続いてforce-app/main/default/components/ReactSampleVFComponent.component
を下記に変更します。
<apex:component>
<!-- Begin Default Content REMOVE THIS -->
<div id="root"></div>
<!-- End Default Content REMOVE THIS -->
</apex:component>
id="root"
のdivタグに対してReactが稼働します。
変更したページとコンポーネントを組織にデプロイしたら、組織にログインして任意のアプリケーション(ここでは[サービス]を選択)のホームに移動します。 「ReactSampleVFPage」の箇所に「Hello, React!」と表示されていれば成功です。
ちょっとだけ複雑なReactを動かしてみる
Hello, Worldだけではつまらないので、ちょっとだけ複雑なReactも動かしてみます。
src/index.jsx
を次に変更します。
import React from 'react';
import {render} from 'react-dom';
import Clock from './Clock';
class App extends React.Component {
constructor(props) {
super(props)
this.state = { name: 'somebody' }
}
onChange(e) {
this.setState( {name: e.target.value} )
}
render() {
return (
<div>
<p>お名前: <input type="text" onChange = { this.onChange.bind(this) } /></p>
<p>{ this.state.name }さん、こんにちは!</p>
<Clock />
</div>
)
}
}
render(<App/>, document.getElementById('root'));
また、src/Clock.jsx
を下記の内容で作成します。
import React from 'react';
import {render} from 'react-dom';
class Clock extends React.Component {
constructor(props) {
super(props);
this.state = {date: new Date()};
}
componentDidMount() {
this.timerID = setInterval(
() => this.tick(),
1000
);
}
componentWillUnmount() {
clearInterval(this.timerID);
}
tick() {
this.setState({
date: new Date()
});
}
render() {
return (
<div>
現在時刻は{this.state.date.toLocaleTimeString()}です。
</div>
);
}
}
export default Clock;
名前の入力を受け付けて、入力された名前に対して挨拶しつつ現在時刻を伝えるReactアプリケーションです。
再度、webpackを実行し、成果物をzipに固めます。
$ ./node_modules/webpack/bin/webpack.js
$ ls dist
bundle.js index.html
$ cd dist
$ zip ReactSample.zip bundle.js index.html
静的リソースReactSampleを新しく作成したReactSample.zipで置き換えて、再度アプリケーション(ここでは[サービス]を選択)のホームに移動します。 作成したReactアプリケーションがSalesforce上で動作していることが確認できます。
まとめ
Visualforce PageとComponentを使って、 ReactアプリケーションをSalesforce上で動作させる方法についてみてきました。 開発したReactアプリケーションをwebpackでまとめれば、あとはそれをSalesforce上で静的リソースとして設定することでVisualforceにて動作させることが可能です。Lightning Web Componentだけでなく、Reactなどの3rd partyの仕組みを使ってもSalesforceの機能を作ることができます。
選択肢の一つとして道具箱に入れてみてください。