[ Laravel 5.4 文档 ] 前端 —— 编译资源(Laravel Mix)

1、简介

Laravel Mix 提供了一套流式 API,使用一些通用的 CSS 和 JavaScript 预处理器为 Laravel 应用定义 Webpack 构建步骤。通过简单的方法链,你可以流式定义资源管道。例如:

mix.js('resources/assets/js/app.js', 'public/js')
   .sass('resources/assets/sass/app.scss', 'public/css');

如果你对如何开始使用 Webpack 和前端资源编译感到困惑,那么你会爱上 Laravel Mix。不过,并不是强制要求在开发期间使用它。你可以自由选择使用任何前端资源管道工具,或者压根不使用。

2、安装 & 设置

安装 Node

在开始接触 Mix 之前,必须首先确保 Node.js 和 NPM 在机器上已经安装:

node -v
npm -v

默认情况下,Laravel Homestead 已经包含了你所需要的一切;不过,如果你没有使用 Vagrant,你也可以从Node 的下载页面轻松的下载安装 Node。

Laravel Mix

接下来,需要安装 Laravel Mix,在新安装的 Laravel 根目录下,你会发现有一个 package.json 文件。该文件包含你所需要的一切,和 composer.json 类似,只不过是用来定义 Node 依赖而非 PHP 依赖,你可以通过运行如下命令来安装需要的依赖:

npm install

如果你正在 Windows 系统上开发,需要在运行 npm install 命令时带上 --no-bin-links

npm install --no-bin-links

3、运行 Mix

Mix 是位于 Webpack 顶层的配置层,所以要运行 Mix 任务你只需要在运行包含在默认 package.json 文件中的其中某个 NPM 脚本即可:

// 运行所有 Mix 任务...
npm run dev

// 运行所有 Mix 任务并减少输出...
npm run production

监控前端资源改变

npm run watch 命令将会持续在终端运行并监听所有相关文件的修改,Webpack将会在发现修改后自动重新编译资源文件:

npm run watch

4、处理样式表

webpack.mix.js 是所有资源编译的入口,可以将其看作 Webpack 的轻量级配置封装层。Mix 任务可以以方法链的方式被链在一起来定义前端资源如何被编译。

Less

要将 Less 编译成 CSS,可以使用 less 方法。下面让我们来编译 app.less 文件到 public/css/app.css

mix.less('resources/assets/less/app.less', 'public/css');

多次调用 less 方法可用于编译多个文件:

mix.less('resources/assets/less/app.less', 'public/css')
   .less('resources/assets/less/admin.less', 'public/css');

如果你想要自定义编译后文件的输出位置,可以将完整的路径信息作为第二个参数传递到 less 方法:

mix.less('resources/assets/less/app.less', 'public/stylesheets/styles.css');

Sass

sass 方法允许你将 Sass 编译成 CSS。你可以像这样使用该方法:

mix.sass('resources/assets/sass/app.scss', 'public/css');

同样,和 less 方法一样,你可以将多个 Sass 文件编译成单个 CSS 文件,甚至自定义结果 CSS 的输出路径:

mix.sass('resources/assets/sass/app.sass', 'public/css')
   .sass('resources/assets/sass/admin.sass', 'public/css/admin');

原生CSS

如果你只想要将多个原生 CSS 样式文件合并到一个文件,可以使用 combine 方法。该方法还支持连接 JavaScript 文件:

mix.combine([
    'public/css/vendor/normalize.css',
    'public/css/vendor/videojs.css'
], 'public/css/all.css');

Source Map

虽然 Source Map 默认被禁用,但是可以通过在 webpack.mix.js 文件中调用 mix.sourceMaps() 来激活。尽管这会带来编译/性能开销,不过在编译资源的时候可以提供额外的调试信息给浏览器的开发者工具:

mix.js('resources/assets/js/app.js', 'public/js')
   .sourceMaps();

5、处理脚本

Mix 还提供了多个特性帮助你处理 JavaScript 文件,例如编译 ECMAScript 2015,模块捆绑,最小化以及合并原生 JavaScript 文件。更好的是,这些都是无缝集成的,不需要额外的自定义配置:

mix.js('resources/assets/js/app.js', 'public/js');

通过这一行代码,你可以实现如下功能:

  • ES2015 语法
  • 编译 .vue 文件
  • 最小化生产环境

代码拆分

捆绑所有应用特定JavaScript和vendor库的一个潜在缺点是进行长期缓存将变得更加困难,例如,单个更新应用代码将会强制浏览器下载所有vendor库,即使它们并没有更新。

如果你想要频繁更新应用的JavaScript,需要考虑对vendor库进行提取和拆分,这样的话,一次修改应用代码不会影响 vendor.js 文件的缓存。Mix 的 extract 方法可以实现这样的功能:

mix.js('resources/assets/js/app.js', 'public/js')
   .extract(['vue'])

extract 方法接收包含所有库的数组或你想要提取到vendor.js文件的模块,使用上述代码作为示例,Mix将会生成如下文件:

  • public/js/manifest.jsWebpack manifest runtime
  • public/js/vendor.jsvendor 库
  • public/js/app.js应用代码

要避免 JavaScript 错误,确保以正确顺序加载这些文件:

<script src="/js/manifest.js"></script>
<script src="/js/vendor.js"></script>
<script src="/js/app.js"></script>

自定义 Webpack 配置

在场景背后,Laravel Mix 引用了预配置的 webpack.config.js 文件来尽可能快的启动和运行。个别情况下,你需要手动编辑这个文件。你可能有一个被引用的特定的加载器或插件,或者可能倾向于使用 Stylus 而不是 Sass,在这些情况下,你有两个选择:

合并

Mix 提供了一个有用的 webpackConfig 方法,从而允许你合并任意简短的 Webpack 配置覆盖。这是一个很吸引人的选择,因为不需要你拷贝或维护自己的webpack.config.js文件副本,webpackConfig方法接收一个对象,该对象包含了任意你想要应用的Webpack指定配置

mix.webpackConfig({
    resolve: {
        modules: [
            path.resolve(__dirname, 'vendor/laravel/spark/resources/assets/js')
        ]
    }
});

引用自己的配置

第二个选择是拷贝Mix的webpack.config.js到自己的项目根目录:

cp node_modules/laravel-mix/setup/webpack.config.js ./

接下来,需要更新 package.json 中的 NPM 脚本,以确保它们不再直接引用 Mix 的配置文件。只需从命令中移除--config="node_modules/laravel-mix/setup/webpack.config.js"即可。完成之后,需要按照需要编辑自己的配置文件。

6、拷贝文件/目录

你可以使用 copy 方法拷贝文件/目录到新路径,这在将node_modules目录下的特定资源文件重新放置到public目录下时很有用:

mix.copy('node_modules/foo/bar.css', 'public/css/bar.css');

7、版本号/缓存刷新

很多开发者会给编译的前端资源添加时间戳或者唯一令牌后缀以强制浏览器加载最新版本而不是代码的缓存副本。Mix 可以使用 version 方法为你处理这种情况。

version 方法会自动附加唯一hash到已编译文件名,从而方便实现缓存刷新:

mix.js('resources/assets/js/app.js', 'public/js')
   .version();

生成版本文件后,还不知提取的文件名,所以,你需要在视图中使用 Laravel 全局的 mix 函数来加载相应的带 hash 值的前端资源。mix 函数会自动判当前的 hash 文件名:

<link rel="stylesheet" href="{{ mix('css/app.css') }}">

由于版本文件在本地开发中没有什么用,你可以只在运行npm run production期间进行版本处理操作:

mix.js('resources/assets/js/app.js', 'public/js');

if (mix.config.inProduction) {
    mix.version();
}

8、通知

在有效的情况下,Mix 会自动为每个捆绑显示操作系统通知,这可以给你一个及时的反馈:编译成功还是失败。不过,某些场景下你可能希望禁止这些通知,一个例子就是在生成环境服务器触发Mix。通知可以通过disableNotifications方法被停用:

mix.disableNotifications();

学院君 has written 716 articles

资深PHP工程师,Laravel学院院长

13 thoughts on “[ Laravel 5.4 文档 ] 前端 —— 编译资源(Laravel Mix)

  1. Aren says:

    mix .sass(‘resources/assets/sass/app.scss’, ‘public/css’),只能监听一个文件,而我想watch整个sass目录下得所有scss文件并打包成一个app.css,该怎么办呢??没有想明白

  2. 星璇天河 says:

    执行安装时,报的错,貌似是内存不够了,请问该如何解决?

    vagrant@homestead:/wwwroot/statistics$ cnpm install –no-bin-links
    npm ERR! Linux 4.4.0-81-generic
    npm ERR! argv “/usr/bin/nodejs” “/usr/bin/npm” “–registry=https://registry.npm.taobao.org” “–cache=/home/vagrant/.npm/.cache/cnpm” “–disturl=https://npm.taobao.org/dist” “–userconfig=/home/vagrant/.cnpmrc” “install” “–no-bin-links”
    npm ERR! node v6.11.1
    npm ERR! npm v3.10.10

    npm ERR! Maximum call stack size exceeded
    npm ERR!
    npm ERR! If you need help, you may report this error at:
    npm ERR!

    npm ERR! Please include the following file with any support request:
    npm ERR! /wwwroot/statistics/npm-debug.log

  3. sycamore says:

    当使用 npm run dev报错:

    @ dev E:\project\mh
    > node_modules/cross-env/dist/bin/cross-env.js NODE_ENV=development node_modules/webpack/bin/webpack.js –progress –hide-modules –config=node_modules/laravel-mix/setup/webpack.config.js

    ‘node_modules’ 不是内部或外部命令,也不是可运行的程序
    或批处理文件。
    npm ERR! code ELIFECYCLE
    npm ERR! errno 1
    npm ERR! @ dev: `node_modules/cross-env/dist/bin/cross-env.js NODE_ENV=development node_modules/webpack/bin/webpack.js –progress –hide-modules –config=node_modules/laravel-mix/setup/webpack.config.js`
    npm ERR! Exit status 1
    npm ERR!
    npm ERR! Failed at the @ dev script.
    npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

    npm ERR! A complete log of this run can be found in:
    npm ERR! C:\Users\Administrator\AppData\Roaming\npm-cache\_logs\2017-06-23T01_22_23_917Z-debug.log

      1. 孙程隆 says:

        我也碰到了这个问题 和 其它问题,搞得我头疼,请问这个问题您是怎么解决的;我们可以交流一下吗?
        我的QQ:951056893
        我的微信: 15727361087

  4. jerkjerkjerk says:

    npm run dev
    0 info it worked if it ends with ok
    1 verbose cli [ '/usr/local/bin/node', '/usr/local/bin/npm', 'run', 'dev' ]
    2 info using npm@3.8.3
    3 info using node@v5.1.0
    4 verbose run-script [ 'predev', 'dev', 'postdev' ]
    5 info lifecycle @~predev: @
    6 silly lifecycle @~predev: no script for predev, continuing
    7 info lifecycle @~dev: @
    8 verbose lifecycle @~dev: unsafe-perm in lifecycle true
    9 verbose lifecycle @~dev: PATH: /usr/local/lib/node_modules/npm/bin/node-gyp-bin:/Users/ericzhou/Desktop/epic.trytv.org/node_modules/.bin:/usr/local/bin:/usr/local/php5/bin:/Library/Frameworks/Python.framework/Versions/3.5/bin:/Library/Frameworks/Python.framework/Versions/2.7/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/go/bin:/Applications/Wireshark.app/Contents/MacOS:/usr/local/go/bin:/Users/ericzhou/go/bin:/usr/local/bin/gdb
    10 verbose lifecycle @~dev: CWD: /Users/ericzhou/Desktop/epic.trytv.org
    11 silly lifecycle @~dev: Args: [ '-c',
    11 silly lifecycle 'node node_modules/cross-env/bin/cross-env.js NODE_ENV=development node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js' ]
    12 silly lifecycle @~dev: Returned: code: 1 signal: null
    13 info lifecycle @~dev: Failed to exec dev script
    14 verbose stack Error: @ dev: `node node_modules/cross-env/bin/cross-env.js NODE_ENV=development node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js`
    14 verbose stack Exit status 1
    14 verbose stack at EventEmitter. (/usr/local/lib/node_modules/npm/lib/utils/lifecycle.js:239:16)
    14 verbose stack at emitTwo (events.js:87:13)
    14 verbose stack at EventEmitter.emit (events.js:172:7)
    14 verbose stack at ChildProcess. (/usr/local/lib/node_modules/npm/lib/utils/spawn.js:24:14)
    14 verbose stack at emitTwo (events.js:87:13)
    14 verbose stack at ChildProcess.emit (events.js:172:7)
    14 verbose stack at maybeClose (internal/child_process.js:818:16)
    14 verbose stack at Process.ChildProcess._handle.onexit (internal/child_process.js:211:5)
    15 verbose pkgid @
    16 verbose cwd /Users/ericzhou/Desktop/epic.trytv.org
    17 error Darwin 15.6.0
    18 error argv "/usr/local/bin/node" "/usr/local/bin/npm" "run" "dev"
    19 error node v5.1.0
    20 error npm v3.8.3
    21 error code ELIFECYCLE
    22 error @ dev: `node node_modules/cross-env/bin/cross-env.js NODE_ENV=development node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js`
    22 error Exit status 1
    23 error Failed at the @ dev script 'node node_modules/cross-env/bin/cross-env.js NODE_ENV=development node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js'.
    23 error Make sure you have the latest version of node.js and npm installed.
    23 error If you do, this is most likely a problem with the package,
    23 error not with npm itself.
    23 error Tell the author that this fails on your system:
    23 error node node_modules/cross-env/bin/cross-env.js NODE_ENV=development node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js
    23 error You can get information on how to open an issue for this project with:
    23 error npm bugs
    23 error Or if that isn't available, you can get their info via:
    23 error npm owner ls
    23 error There is likely additional logging output above.
    24 verbose exit [ 1, true ]

    大神什么原因啊

    1. feng says:

      虽然不知道能不能解决你的问题,但是我在编译的时候发现,在package.json里面,这段路径有点问题“node_modules/cross-env/dist/bin/cross-env.js”,你可以自己去node_modules看,cross-env的路劲发生了变化,虽然我的报错和你的不一样但还是希望能帮到你

发表评论

标记为*的字段是必填项(邮箱地址不会被公开)

你可以使用这些HTML 标签和属性: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>