Phoenix框架 - 在子目录中执行NPM脚本

时间:2017-11-19 23:11:28

标签: npm elixir phoenix-framework

在我的凤凰应用程序中,我正在运行一个位于应用程序内assets/目录中的React前端...它拥有自己的package.json文件,我想能够从Phoenix应用程序的mix.exs文件中运行别名的NPM脚本。我一直在尝试使用Elixir System.cmd(),但它似乎没有做到这一点。

基本上,我为我的前端设置了一个lint命令 - 在assets/package.json,我已经

"lint": "eslint ./*.js ./js/*.js || exit 0"

并从$ npm run lint目录运行assets/按预期工作......但是只能从应用程序的顶级运行命令就可以了。

在我的mix.exs文件中,我正在尝试像这样的别名:

defp aliases do
  [
    "lint": [System.cmd("npm", ["run lint"], cd: "assets")
  ]
end

但是运行mix lint会产生一个非常冗长的错误:

** (FunctionClauseError) no function clause matching in Mix.Task.run_alias/3    

The following arguments were given to Mix.Task.run_alias/3:

    # 1
    [{"\nUsage: npm <command>\n\nwhere <command> is one of:\n    access, adduser, bin, bugs, c, cache, completion, config,\n    ddp, dedupe, deprecate, dist-tag, docs, edit, explore, get,\n    help, help-search, i, init, install, install-test, it, link,\n    list, ln, login, logout, ls, outdated, owner, pack, ping,\n    prefix, prune, publish, rb, rebuild, repo, restart, root,\n    run, run-script, s, se, search, set, shrinkwrap, star,\n    stars, start, stop, t, tag, team, test, tst, un, uninstall,\n    unpublish, unstar, up, update, v, version, view, whoami\n\nnpm <cmd> -h     quick help on <cmd>\nnpm -l           display full usage info\nnpm help <term>  search for help on <term>\nnpm help npm     involved overview\n\nSpecify configs in the ini-formatted file:\n    /Users/user/.npmrc\nor on the command line via: npm <command> --key value\nConfig info can be viewed via: npm help config\n\nnpm@3.10.10 /Users/user/.nvm/versions/node/v6.11.1/lib/node_modules/npm\n", 1}]

    # 2
    []

    # 3
    :ok

Attempted function clauses (showing 3 out of 3):

    defp run_alias([h | t], alias_args, _res) when is_binary(h)
    defp run_alias([h | t], alias_args, _res) when is_function(h, 1)
    defp run_alias([], _alias_task, res)

(mix) lib/mix/task.ex:331: Mix.Task.run_alias/3
(mix) lib/mix/task.ex:266: Mix.Task.run/2
(mix) lib/mix/cli.ex:75: Mix.CLI.run_task/2
(elixir) lib/code.ex:376: Code.require_file/2

好的,显然我做错了什么。是否可以在Phoenix应用程序的子目录上执行NPM命令?

3 个答案:

答案 0 :(得分:3)

首先,runlint应该是参数列表中的单独字符串。

其次,您拥有的代码将立即运行命令,而不是在调用别名时。

您可以使用"run -e ..."别名在别名中执行任意代码,如下所示:

"lint": [~s|run -e 'System.cmd("npm", ["run", "lint"], cd: "assets")'|)

(我使用~s||语法只是为了更容易输入包含单引号和双引号的字符串。)

答案 1 :(得分:0)

还有一个扩展名可用于执行此操作,但不幸的是它无法遍历路径。但也许会被修补。

https://github.com/verdammelt/mix_npm

答案 2 :(得分:0)

替代~s||带有 cd 的符号,我们也可以在 npm 命令中使用 --prefix 标志。

lintjs: ["cmd npm run format:ci --prefix assets"]

如果使用伞形项目,请在其运行的应用中定义别名,并在项目根目录中添加别名。

<root>/mix.exs

defp aliases do
    [
      # run `mix setup` in all child apps
      setup: ["cmd mix setup"],
      # app-specific alias defined in onstage_web/mix.exs
      lint: ["cmd --app myapp_name mix lintjs"]
    ]
end

<root>/apps/myapp_name/mix.exs

defp aliases do
    [
      # run npm install in child app
      setup: ["deps.get", "cmd npm install --prefix assets"],,
      # simplified/equivalent of accepted answer
      lintjs: ["cmd npm run format:ci --prefix assets"]
    ]
end

现在,我们可以从项目根目录运行 mix lint 来对子应用中的 JS 进行 lint。

另外,请记住在进行更改后运行 mix compile