我应该如何在 Phoenix 1.5 的模板中包含 javascript
How should I include javascript in a template in Phoenix 1.5
我试图在我使用 webpack 的 phoenix 1.5 项目中包含一个使用 chart.js 的 javascript 文件。当我在模板中添加类似 <script>require('/js/graph').Graph.draw()</script>
的内容时,我在浏览器控制台中看到错误 Uncaught ReferenceError: require is not defined
,并且未呈现图形。
package.json
{
"repository": {},
"license": "MIT",
"scripts": {
"deploy": "webpack --mode production",
"watch": "webpack --mode development --watch"
},
"dependencies": {
"chart.js": "^2.9.3",
"phoenix": "file:../deps/phoenix",
"phoenix_html": "file:../deps/phoenix_html"
},
"devDependencies": {
"@babel/core": "^7.0.0",
"@babel/preset-env": "^7.0.0",
"babel-loader": "^8.0.0",
"copy-webpack-plugin": "^4.5.0",
"css-loader": "^2.1.1",
"mini-css-extract-plugin": "^0.4.0",
"optimize-css-assets-webpack-plugin": "^5.0.1",
"terser-webpack-plugin": "^1.1.0",
"webpack": "4.4.0",
"webpack-cli": "^3.3.2"
}
}
webpack.config.js
const path = require('path');
const glob = require('glob');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const TerserPlugin = require('terser-webpack-plugin');
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');
module.exports = (env, options) => ({
optimization: {
minimizer: [
new TerserPlugin({ 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$/,
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: '../' }])
]
});
graph.js
export const Graph = {
draw() {
const Chart = require('char.js');
const ctx = document.getElementById('myChart');
const myChart = new Chart(ctx, {
type: 'bar',
data: {
labels: ['Red', 'Blue', 'Yellow', 'Green', 'Purple', 'Orange'],
datasets: [{
label: '# of Votes',
data: [12, 19, 3, 5, 2, 3],
backgroundColor: [
'rgba(255, 99, 132, 0.2)',
'rgba(54, 162, 235, 0.2)',
'rgba(255, 206, 86, 0.2)',
'rgba(75, 192, 192, 0.2)',
'rgba(153, 102, 255, 0.2)',
'rgba(255, 159, 64, 0.2)'
],
borderColor: [
'rgba(255, 99, 132, 1)',
'rgba(54, 162, 235, 1)',
'rgba(255, 206, 86, 1)',
'rgba(75, 192, 192, 1)',
'rgba(153, 102, 255, 1)',
'rgba(255, 159, 64, 1)'
],
borderWidth: 1
}]
},
options: {
scales: {
yAxes: [{
ticks: {
beginAtZero: true
}
}]
}
}
});
}
}
index.html.eex
<div class="phx-hero">
<h2>Graph: </h2>
<canvas id="myChart" width="400" height="400"></canvas>
</div>
<script>require('/js/graph').Graph.draw()</script>
我有一个 phoenix 1.3 项目,这就是我在模板中使用 javascript 的方式,但它使用的是早午餐。我对 webpack 这样做正确吗?
让我们假设您希望它在所有页面中 运行。在这种情况下 "include" 你的 graph.js 在 app.js
// app.js
import {Graph} from 'graph';
Graph.draw();
但如果您只在特定页面需要它,请在 webpack.config.js
中创建新的 "entry"
// webpack.config.js
entry: {
'./js/app.js': glob.sync('./vendor/**/*.js').concat(['./js/app.js']),
'./js/mypage.js': 'js/mypage.js'
},
然后输入 mypage.js 与我在第一种情况下建议的代码相同,然后在您的页面中包含 mypage.js,如下所示:
<script src='<%= static_path("js/mypage.js") %>'></script>
应在布局中包含 app.js 文件后添加此行(我认为默认情况下它包含在那里)
编辑
我意识到 phoenix 默认 Webpack 具有硬编码输出,因此所有 js 代码仍将以相同的输出文件名出现,因此必须应用以下更改
入口点
entry: {
'./js/app.js': glob.sync('./vendor/**/*.js').concat(['./js/app.js']),
'./js/graph.js': glob.sync('./vendor/**/*.js').concat(['./js/graph.js'])
},
输出
请注意,'../priv/static/js'
已更改为 '../priv/static'
,filename: 'app.js'
已更改为 filename: '[name]'
,
output: {
filename: '[name]',
path: path.resolve(__dirname, '../priv/static')
},
插件
new CopyWebpackPlugin([{ from: 'static/', to: '../' }])
改为 new CopyWebpackPlugin([{ from: 'static/', to: '' }])
plugins: [
new MiniCssExtractPlugin({ filename: 'css/app.css' }),
new CopyWebpackPlugin([{ from: 'static/', to: '' }])
]
请注意,如果您之前进行了一些更改,您可能会略有不同,只需注意路径,因为 output.path 现在在文件夹结构中向上一级!
我试图在我使用 webpack 的 phoenix 1.5 项目中包含一个使用 chart.js 的 javascript 文件。当我在模板中添加类似 <script>require('/js/graph').Graph.draw()</script>
的内容时,我在浏览器控制台中看到错误 Uncaught ReferenceError: require is not defined
,并且未呈现图形。
package.json
{
"repository": {},
"license": "MIT",
"scripts": {
"deploy": "webpack --mode production",
"watch": "webpack --mode development --watch"
},
"dependencies": {
"chart.js": "^2.9.3",
"phoenix": "file:../deps/phoenix",
"phoenix_html": "file:../deps/phoenix_html"
},
"devDependencies": {
"@babel/core": "^7.0.0",
"@babel/preset-env": "^7.0.0",
"babel-loader": "^8.0.0",
"copy-webpack-plugin": "^4.5.0",
"css-loader": "^2.1.1",
"mini-css-extract-plugin": "^0.4.0",
"optimize-css-assets-webpack-plugin": "^5.0.1",
"terser-webpack-plugin": "^1.1.0",
"webpack": "4.4.0",
"webpack-cli": "^3.3.2"
}
}
webpack.config.js
const path = require('path');
const glob = require('glob');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const TerserPlugin = require('terser-webpack-plugin');
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');
module.exports = (env, options) => ({
optimization: {
minimizer: [
new TerserPlugin({ 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$/,
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: '../' }])
]
});
graph.js
export const Graph = {
draw() {
const Chart = require('char.js');
const ctx = document.getElementById('myChart');
const myChart = new Chart(ctx, {
type: 'bar',
data: {
labels: ['Red', 'Blue', 'Yellow', 'Green', 'Purple', 'Orange'],
datasets: [{
label: '# of Votes',
data: [12, 19, 3, 5, 2, 3],
backgroundColor: [
'rgba(255, 99, 132, 0.2)',
'rgba(54, 162, 235, 0.2)',
'rgba(255, 206, 86, 0.2)',
'rgba(75, 192, 192, 0.2)',
'rgba(153, 102, 255, 0.2)',
'rgba(255, 159, 64, 0.2)'
],
borderColor: [
'rgba(255, 99, 132, 1)',
'rgba(54, 162, 235, 1)',
'rgba(255, 206, 86, 1)',
'rgba(75, 192, 192, 1)',
'rgba(153, 102, 255, 1)',
'rgba(255, 159, 64, 1)'
],
borderWidth: 1
}]
},
options: {
scales: {
yAxes: [{
ticks: {
beginAtZero: true
}
}]
}
}
});
}
}
index.html.eex
<div class="phx-hero">
<h2>Graph: </h2>
<canvas id="myChart" width="400" height="400"></canvas>
</div>
<script>require('/js/graph').Graph.draw()</script>
我有一个 phoenix 1.3 项目,这就是我在模板中使用 javascript 的方式,但它使用的是早午餐。我对 webpack 这样做正确吗?
让我们假设您希望它在所有页面中 运行。在这种情况下 "include" 你的 graph.js 在 app.js
// app.js
import {Graph} from 'graph';
Graph.draw();
但如果您只在特定页面需要它,请在 webpack.config.js
中创建新的 "entry"// webpack.config.js
entry: {
'./js/app.js': glob.sync('./vendor/**/*.js').concat(['./js/app.js']),
'./js/mypage.js': 'js/mypage.js'
},
然后输入 mypage.js 与我在第一种情况下建议的代码相同,然后在您的页面中包含 mypage.js,如下所示:
<script src='<%= static_path("js/mypage.js") %>'></script>
应在布局中包含 app.js 文件后添加此行(我认为默认情况下它包含在那里)
编辑
我意识到 phoenix 默认 Webpack 具有硬编码输出,因此所有 js 代码仍将以相同的输出文件名出现,因此必须应用以下更改
入口点
entry: {
'./js/app.js': glob.sync('./vendor/**/*.js').concat(['./js/app.js']),
'./js/graph.js': glob.sync('./vendor/**/*.js').concat(['./js/graph.js'])
},
输出
请注意,'../priv/static/js'
已更改为 '../priv/static'
,filename: 'app.js'
已更改为 filename: '[name]'
,
output: {
filename: '[name]',
path: path.resolve(__dirname, '../priv/static')
},
插件
new CopyWebpackPlugin([{ from: 'static/', to: '../' }])
改为 new CopyWebpackPlugin([{ from: 'static/', to: '' }])
plugins: [
new MiniCssExtractPlugin({ filename: 'css/app.css' }),
new CopyWebpackPlugin([{ from: 'static/', to: '' }])
]
请注意,如果您之前进行了一些更改,您可能会略有不同,只需注意路径,因为 output.path 现在在文件夹结构中向上一级!