For future reference:
$ mix phx.new react_demo --no-ecto
* creating react_demo/config/config.exs
...
* creating react_demo/assets/static/robots.txt
Fetch and install dependencies? [Yn] Y
* running mix deps.get
* running cd assets && npm install && node node_modules/webpack/bin/webpack.js --mode development
* running mix deps.compile
We are almost there! The following steps are missing:
$ cd react_demo
Start your Phoenix app with:
$ mix phx.server
You can also run your app inside IEx (Interactive Elixir) as:
$ iex -S mix phx.server
$ cd react_demo
react_demo$ mix phx.server
Compiling 12 files (.ex)
Generated react_demo app
[info] Running ReactDemoWeb.Endpoint with cowboy 2.6.3 at 0.0.0.0:4000 (http)
[info] Access ReactDemoWeb.Endpoint at http://localhost:4000
Webpack is watching the files…
Hash: 1fc94cc9b786e491ad40
Version: webpack 4.4.0
Time: 513ms
Built at: 7/12/2019 1:08:54 PM
Asset Size Chunks Chunk Names
../css/app.css 10.6 KiB ./js/app.js [emitted] ./js/app.js
app.js 7.26 KiB ./js/app.js [emitted] ./js/app.js
../favicon.ico 1.23 KiB [emitted]
../images/phoenix.png 13.6 KiB [emitted]
../robots.txt 202 bytes [emitted]
[0] multi ./js/app.js 28 bytes {./js/app.js} [built]
[../deps/phoenix_html/priv/static/phoenix_html.js] 2.21 KiB {./js/app.js} [built]
[./css/app.css] 39 bytes {./js/app.js} [built]
[./js/app.js] 493 bytes {./js/app.js} [built]
+ 2 hidden modules
Child mini-css-extract-plugin node_modules/css-loader/dist/cjs.js!css/app.css:
[./node_modules/css-loader/dist/cjs.js!./css/app.css] 284 bytes {mini-css-extract-plugin} [built]
[./node_modules/css-loader/dist/cjs.js!./css/phoenix.css] 10.9 KiB {mini-css-extract-plugin} [built]
+ 1 hidden module
Check in the browser http://localhost:4000/ to see the “Phoenix Framework” page.
^C
BREAK: (a)bort (c)ontinue (p)roc info (i)nfo (l)oaded
(v)ersion (k)ill (D)b-tables (d)istribution
a
react_demo $ cd assets
assets $ npm i -g npm-check-updates
.npm-global/bin/npm-check-updates -> .npm-global/lib/node_modules/npm-check-updates/bin/npm-check-updates
.npm-global/bin/ncu -> .npm-global/lib/node_modules/npm-check-updates/bin/ncu
+ npm-check-updates@3.1.18
added 260 packages from 118 contributors in 8.122s
assets $ ncu -u
Upgrading react_demo/assets/package.json
[====================] 12/12 100%
@babel/core ^7.0.0 → ^7.5.4
@babel/preset-env ^7.0.0 → ^7.5.4
babel-loader ^8.0.0 → ^8.0.6
copy-webpack-plugin ^4.5.0 → ^5.0.3
css-loader ^2.1.1 → ^3.0.0
mini-css-extract-plugin ^0.4.0 → ^0.7.0
optimize-css-assets-webpack-plugin ^4.0.0 → ^5.0.3
uglifyjs-webpack-plugin ^1.2.4 → ^2.1.3
webpack 4.4.0 → 4.35.3
webpack-cli ^2.0.10 → ^3.3.5
Run npm install to install new versions.
assets $ npm i
npm WARN assets No description
added 119 packages from 103 contributors, removed 596 packages, updated 72 packages, moved 3 packages and audited 8034 packages in 17.606s
found 63 high severity vulnerabilities
run `npm audit fix` to fix them, or `npm audit` for details
assets $ npm i -D @babel/preset-react
npm WARN assets No description
+ @babel/preset-react@7.0.0
added 7 packages from 1 contributor and audited 8056 packages in 4.55s
found 63 high severity vulnerabilities
run `npm audit fix` to fix them, or `npm audit` for details
assets $ npm i -P react react-dom
npm WARN assets No description
+ react@16.8.6
+ react-dom@16.8.6
added 5 packages and audited 8082 packages in 4.779s
found 63 high severity vulnerabilities
run `npm audit fix` to fix them, or `npm audit` for details
assets $
Delete assets/.babelrc
assets $ rm .babelrc
Create assets/babel.config.js
module.exports = function (api) {
api.cache(true);
const presets = [
'@babel/preset-env',
'@babel/preset-react',
]
const plugins = [
]
return {
presets,
plugins
};
}
Modify assets/webpack.config.js
const path = require('path');
const glob = require('glob');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');
module.exports = (env, options) => ({
optimization: {
minimizer: [
new UglifyJsPlugin({ cache: true, parallel: true, sourceMap: false }),
new OptimizeCSSAssetsPlugin({})
]
},
entry: {
'./js/app.js': glob.sync('./vendor/**/*.js').concat(['./js/app.js'])
},
output: {
filename: 'app.js',
path: path.resolve(__dirname, '../priv/static/js')
},
module: {
rules: [
{
test: /\.(js|jsx)$/, /* add jsx */
exclude: /node_modules/,
use: {
loader: 'babel-loader'
}
},
{
test: /\.css$/,
use: [MiniCssExtractPlugin.loader, 'css-loader']
}
]
},
plugins: [
new MiniCssExtractPlugin({ filename: '../css/app.css' }),
new CopyWebpackPlugin([{ from: 'static/', to: '../' }])
]
});
Modify assets/js/app.js
:
// We need to import the CSS so that webpack will load it.
// The MiniCssExtractPlugin is used to separate it out into
// its own CSS file.
import css from "../css/app.css"
// webpack automatically bundles all modules in your
// entry points. Those entry points can be configured
// in "webpack.config.js".
//
// Import dependencies
//
import "phoenix_html"
// Import local files
//
// Local files can be imported directly using relative paths, for example:
// import socket from "./socket"
import React from 'react'
import ReactDOM from 'react-dom'
const App = ({ title }) =>
<div>{title}</div>
const title = "Hello World!"
ReactDOM.render(
<App title={title} />,
document.getElementById('app')
)
Replace contents of react_demo/lib/react_demo_web/templates/page/index.html.eex
with
<div id="app"></div>
$ cd ..
react_demo $ mix phx.server
Compiling 1 file (.ex)
[info] Running ReactDemoWeb.Endpoint with cowboy 2.6.3 at 0.0.0.0:4000 (http)
[info] Access ReactDemoWeb.Endpoint at http://localhost:4000
webpack is watching the files…
Hash: 422aabb9c911039eccdd
Version: webpack 4.35.3
Time: 683ms
Built at: 07/12/2019 2:00:54 PM
Asset Size Chunks Chunk Names
../css/app.css 10.6 KiB ./js/app.js [emitted] ./js/app.js
../favicon.ico 1.23 KiB [emitted]
../images/phoenix.png 13.6 KiB [emitted]
../robots.txt 202 bytes [emitted]
app.js 911 KiB ./js/app.js [emitted] ./js/app.js
Entrypoint ./js/app.js = ../css/app.css app.js
[0] multi ./js/app.js 28 bytes {./js/app.js} [built]
[../deps/phoenix_html/priv/static/phoenix_html.js] 2.21 KiB {./js/app.js} [built]
[./css/app.css] 39 bytes {./js/app.js} [built]
[./js/app.js] 790 bytes {./js/app.js} [built]
[./node_modules/webpack/buildin/global.js] (webpack)/buildin/global.js 472 bytes {./js/app.js} [built]
+ 13 hidden modules
Child mini-css-extract-plugin node_modules/css-loader/dist/cjs.js!css/app.css:
Entrypoint mini-css-extract-plugin = *
[./node_modules/css-loader/dist/cjs.js!./css/app.css] 282 bytes {mini-css-extract-plugin} [built]
[./node_modules/css-loader/dist/cjs.js!./css/phoenix.css] 10.9 KiB {mini-css-extract-plugin} [built]
+ 1 hidden module
Looking at http://localhost:4000/ you should see:
The resulting assets/package.json
:
{
"repository": {},
"license": "MIT",
"scripts": {
"deploy": "webpack --mode production",
"watch": "webpack --mode development --watch"
},
"dependencies": {
"phoenix": "file:../deps/phoenix",
"phoenix_html": "file:../deps/phoenix_html",
"react": "^16.8.6",
"react-dom": "^16.8.6"
},
"devDependencies": {
"@babel/core": "^7.5.4",
"@babel/preset-env": "^7.5.4",
"@babel/preset-react": "^7.0.0",
"babel-loader": "^8.0.6",
"copy-webpack-plugin": "^5.0.3",
"css-loader": "^3.0.0",
"mini-css-extract-plugin": "^0.7.0",
"optimize-css-assets-webpack-plugin": "^5.0.3",
"uglifyjs-webpack-plugin": "^2.1.3",
"webpack": "4.35.3",
"webpack-cli": "^3.3.5"
}
}