Phoenix是目前最火的后端Web框架之一,它基于Elixir,一款基于Erlang VM的语言,它有着卓越的性能和Ruby般的开发效率。而Webpack又是目前前端构建工具中冉冉升起的新星,它有着诸多非常强大的功能,几乎能提供任何你想要的前端构建流程。那我们快来看一下怎样将两者结合起来吧!
1. 初始化Phoenix应用
这里我们不用--no-brunch
flag,因为使用这个flag虽然不会引入Brunch,但是会少创建一些文件夹和文件,如web/static/js
等,这里我们会在创建之后把Brunch相关文件修改为Webpack的对应文件。
mix phoenix.new webpack_integration
删除brunch-config.js
rm brunch-config.js
清空Brunch相关的dependencies
{
"repository": {
},
"dependencies": {
}
}
2. 添加 Webpack
添加webpack
npm install --save-dev webpack
在项目根目录中创建webpack.config.js
,并写入如下代码:
module.exports = {
entry: "./web/static/js/app.js",
output: {
path: "./priv/static/js",
filename: "app.js"
}
};
这段代码告诉webpack找到web/static/js/app.js
的内容并且编译合并到priv/static/js/app.js
。
我们在package.json
中定义npm start
脚本来运行webpack。
{
"scripts": {
"start": "webpack --watch-stdin --progress --color"
}
}
在phoenix的config/dev.exs
定义watchers
参数,这里的意思是在mix phoenix.server
服务器启动的时候运行npm start
命令。
config :webpack_integration, WebpackIntegration.Endpoint,
watchers: [npm: ["start"]]
安装phoenix和npm的所有依赖,初始化数据库,并启动服务器:
mix deps.get
npm install
mix ecto.create
mix phoenix.server
3. 增加 Babel 和 CSS 支持
安装babel依赖,这样你就可以使用JavaScript的ES2015语法。
npm install babel-loader babel-core babel-preset-es2015 --save-dev
在webpack.config.js
增加如下的output
设置:
module.exports = {
// entry and output options...
module: {
loaders: [{
test: /\.js$/,
exclude: /node_modules/,
loader: "babel",
query: {
presets: ["es2015"]
}
}]
}
}
这些规则是说应用所需的所有.js
文件都通过Babel转义,一旦配置完成,重启服务器,所有Babel提供的JavaScript特性都被支持。
设置加载路径
在Webpack中使用import
或require
需要明确的相对你工作目录的路径,假设你有这两个文件:
app.js
components/filePicker.js
并且我们需要在app.js
中引入filePicker
组件:
// Brunch
import filePicker from 'components/filePicker';
// Webpack
import filePicker from './components/filePicker';
我们可以看到Brunch和Webpack在ES2015导入/加载方面的不同。这里我们还需要告诉Webpack寻找node_modules
。
module.exports = {
// Leave the entry, output, and module options we set previously
resolve: {
modulesDirectories: [ "node_modules", __dirname + "/web/static/js" ]
}
}
最后一步是采用npm管理phoenix_html
和phoenix
所需依赖,这些文件是通过hex安装的。
npm install file:deps/phoenix_html file:deps/phoenix --save
这样我们就可以像平常那样导入模块了:
import "phoenix_html";import { Socket } from "phoenix";
重启服务器,Phoenix JavaScript的文件就被包括在编译的文件里了。
CSS and Webpack
如果你之前使用过Webpack,你可能会看到CSS文件从独立的组件中引入。Webpack会在加载页面时内嵌css代码,而非生成单独的css文件。这里,我们只是复现Brunch的功能,我们将CSS从JavaScript中分离出去。这种处理CSS的方式和Webpack标准教程有些差异。
var ExtractTextPlugin = require("extract-text-webpack-plugin");
module.exports = {
entry: ["./web/static/css/app.css", "./web/static/js/app.js"],
output: {
path: "./priv/static",
filename: "js/app.js"
},
module: {
loaders: [{
test: /\.js$/,
exclude: /node_modules/,
loaders: ["babel"],
include: __dirname,
query: {
presets: ["es2015"]
}
}, {
test: /\.css$/,
loader: ExtractTextPlugin.extract("style", "css")
}]
},
plugins: [
new ExtractTextPlugin("css/app.css")
]
};
With this configuration, webpack will grab the web/static/css/app.css
file, parse the CSS and move it to priv/static/css/app.css
. Restart your Phoenix server to see the stylesheets working. The only thing missing now are the static assets.
通过这样设置,Webpack就能够提取web/static/css/app.css
并将它移动到priv/static/css/app.css
。重启Phoenix服务器就能看到样式表啦。现只剩静态资源文件没有处理了。
4. 处理静态资源文件
最后,我们要移动静态资源文件使得别人能够访问它们。默认静态资源文件在web/static/assets
目录下,我们需要将它们移动到priv/static
下。举个例子,web/static/assets/favicon.ico
会被移动到priv/static/favicon.ico
。
为实现这一功能,我们需要安装copy-webpack-plugin
这个插件。
并且在webpack.config.js
的plugins数组中添加如下:
var CopyWebpackPlugin = require("copy-webpack-plugin");
module.exports {
// ...
plugins: [
new ExtractTextPlugin("css/app.css"),
new CopyWebpackPlugin([{ from: "./web/static/assets" }])
]
}
添加到web/static/assets
的资源文件并不自动拷贝,如果一个文件被添加,你需要重启Webpack。
5. 生产环境构建
最后一步是让webpack构建生产环境的资源文件。在package.json
中添加如下代码:
{
"scripts": {
"compile": "webpack -p"
}
}
现在,只需要运行npm run
即可变异生产环境下的资源文件。
至此,我们已经使用Webpack替代了Brunch的所有功能。快点自己动手试试吧!如果在试验过程中遇到问题,可以看看这个repo。
扩展阅读
[1] http://manukall.de/2015/05/01/automatically-building-your-phoenix-assets-with-webpack/
[2] http://matthewlehner.net/using-webpack-with-phoenix-and-elixir/