zzxworld

Laravel Mix 上手指南

Laravel 是个了不起的 PHP Web 开发框架。项目结构清晰,功能模块齐全,代码风格统一规范,是我目前用起来最为顺手的项目框架。Laravel Mix 则是 Laravel 框架中的一个前端打包工具,它带给我的使用体验和 Laravel 一样优秀。

和 Webpack 对比

说到前端的打包工具,自然是绕不开 Webpack。Webpack 在前端构建的功能表现上无容置疑,我在好几个项目中都有使用。

但 Webpack 在丰富的功能特性下,是繁琐的配置工作。关于这一点,我贴段代码让各位感受一下。

const path = require('path');
const webpack = require('webpack')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const TerserPlugin = require('terser-webpack-plugin')
const Dotenv = require('dotenv')

const defaultConfig = {
    entry: './src/main.js',

    output: {
        filename: '[name].[fullhash].js',
    },

    resolve: {
        modules: [path.resolve(__dirname, 'src'), 'node_modules'],
    },

    module: {
        rules: [
            {
                test: /\.js$/,
                exclude: /node_modules/,
                use: ['babel-loader']
            },
            {
                test: /\.(c|sc|sa)ss/,
                use: [
                    MiniCssExtractPlugin.loader,
                    'css-loader',
                    'sass-loader'
                ]
            }
        ]
    },

    plugins: [
        new MiniCssExtractPlugin({
            filename: '[name].[fullhash].css'
        }),
        new HtmlWebpackPlugin({
            template: 'template.html'
        })
    ]
}

Dotenv.config()

module.exports = env => {
    const config = Object.assign({}, defaultConfig)
    let API_URL = process.env.DEV_API_URL

    if (env.prod) {
        API_URL = process.env.PROD_API_URL
        config.mode = 'production'
        config.optimization = {
            minimize: true,
            minimizer: [
                new TerserPlugin({
                    extractComments: false,
                })
            ]
        }
    } else {
        config.mode = 'development'
        config.devtool = 'source-map'
        config.devServer = {
            host: 'localhost',
            port: 8000,
            hot: true
        }
    }

    config.plugins.push(new webpack.DefinePlugin({
        API_URL: JSON.stringify(API_URL)
    }))

    return config
}

这是我在一个小项目中使用的 Webpack 配置代码。作为一个非专业前端人员,在不经常鼓捣这些配置项的情况下,花了大半天时间靠搜索引擎才拼凑出这样一份「能用的」配置。问题是后面可能很长时间不会再关注这份配置文件,所以之后如果再有调整,可能一切又要重来一遍。

再来看看我在另一个项目中使用的 Laravel Mix 配置:

const mix = require('laravel-mix');

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

这两份配置涉及的模块和功能需求基本一致,但所需的配置代码却不在一个量级。即便不关注配置的代码量,只从「心智负担」方面来衡量,我也倾向于选择 Laravel Mix。

使用 Webpack 配置项

选择 Laravel Mix 并不意味着放弃了 Webpack。Laravel Mix 项目网站的一句话其实就很好的概括了它与 Webpack 之间的关系:

An elegant wrapper around Webpack for the 80% use case.

Laravel Mix 并没有发明新轮子,只是在 Webpack 外面套了一层「优雅」的外衣,让 Webpack 更加易用。

就像上面引用的那句话所说。在 80% 的使用场景下,直接用 Laravel Mix 提供的「包装配置项」就可以了。但如果自己的需求不在这 80% 的范围中,Laravel Mix 还提供了直接配置 Webpack 的接口。

比如想配置一下 Webpack 的 import 搜索路径:

mix.webpackConfig({
    resolve: {
        modules: [
            path.resolve(__dirname, 'resources/js/app'),
            'node_modules'
        ]
    }
})

所以即便我有使用特殊 Webpack 配置项的需求,使用 Laravel Mix 也不会有任何问题。

在 Laravel 之外使用

作为 Laravel 开发框架的一部分,Laravel Mix 并不依赖于 Laravel。我想只要是可以使用 Webpack 的地方,都可以尝试使用一下 Laravel Mix。作为本文的结尾,就以在一个单独的项目中引如 Laravel Mix 作为结尾吧。

作为前端打包工具,需要提前安装好 JavaScript 的包管理命令:npm。我之前有分享过一篇相关文章,不熟悉的朋友可以前去了解一下:

JavaScript 包管理工具指南了解 JavaScript 的各种包管理工具。

有了 npm 后,创建项目目录并安装 Laravel Mix:

mkdir demo && cd demo
npm init -y
npm install laravel-mix -D

这样就创建好了一个 demo 项目目录,并安装好了 Laravel Mix。接下来需要创建 Laravel Mix 的配置文件:

touch webpack.mix.js

在这个文件中就可以配置要打包的文件和输出目录了。比如在当前目录下创建一个 app.js 文件,打包后代码输出到 public 目录。只要这么一行配置:

const mix = require('laravel-mix');

mix.js('app.js', 'public');

然后执行 npx mix 命令就可以输出打包内容了。这个命令只适用于开发状态下的一次性使用,另外还有其他场景下用的命令:

  • 监视入口文件,有修改时自动打包:npx mix watch
  • 压缩输出的打包文件以便线上使用:npx mix --production

有了 Laravel Mix,前端打包的配置工作对我来说就不再是一项头疼的琐事。