在 Laravel 之外使用 Laravel-mix 的一点小坑,字体正确无法加载。 | Laravel China 社区 - 高品质的 Laravel 和 PHP 开发者社区

[在 Laravel 之外使用 Laravel-mix 的一点小坑,字体正确无法加载。 | Laravel China 社区 - 高品质的 Laravel 和 PHP 开发者社区]

背景

项目不是 Laravel,需要写前端代码,然后 webpack 的配置不熟悉,所以选择了使用 laravel-mix 来编译前端代码。

前端选择的是 iview 来写页面。

使用 iview 需要 import 'iview/dist/styles/iview.css';

问题来源与解决过程

webpack.mix.js 的配置内容如下:

const fs = require('fs')
const mix = require('laravel-mix')
const path = require('path')
const webpack = require('webpack')

/**
 * webpack 配置
 */

mix.webpackConfig({
  output: {
    // 依据该路径进行编译以及异步加载
    publicPath: 'assets/main/',
    // 注意开发期间不加 hash,以免自动刷新失败
    chunkFilename: `js/chunk[name].${ mix.inProduction() ? '[chunkhash].' : '' }js`
  },

  plugins: [
    // 不打包 moment.js 的语言文件以减小体积
    new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/),
  ]
})

/**
 * SPA 资源编译
 */

mix
  .setPublicPath(path.normalize('Demo/public/assets/main'))
  .options({
    processCssUrls: false
  })
  .js('resources/assets/main/js/app.js', 'js')
  .extract([
    'axios',
    'lodash',
    'vue',
    'vue-router',
  ])
  .autoload({
    vue: ['Vue']
  })

/**
 * 发布时文件名打上 hash 以强制客户端更新
 */

if (mix.inProduction()) {
  mix.version()
} else {
  mix.disableNotifications()
}

// 加载 .env 中 browserSync proxy 的配置
let paths = fs.readFileSync('.env', 'utf8').match(/BROWSERSYNC_PROXY=\S*/)
let proxy = paths ? paths[0].split('=')[1] : 'server.test'

/**
 * 本地调试 dev-server 配置
 */

mix.browserSync({
  proxy,
  files: [
    'resources/assets/js/**/*.js',
    'Demo/Site/View/**/*.tpl.php',
  ]
})

  .disableNotifications()

最后编译后的访问结果是在控制台中获取到如下2个字体加载错误:

[file

](https://lccdn.phphub.org/uploads/images/201711/22/6324/kygTS0vPha.png)

而文件的实际打包路径是:Demo/public/assets/main/fonts

[file

](https://lccdn.phphub.org/uploads/images/201711/22/6324/FzZDHOmOA5.png)

各种百度,谷歌后没找到有用的信息。有如下相关信息:

iview icon打包问题 #1499

这个里面有个也许可行的方案,但是配置的时候找不到 utils ,utils 是 require进去的。我没找到这个 utils 的具体文件内容

segmentfault: iview 打包之后 找不到自带的icon图片,而且路径重复,点解

剩下还查过很多,都没有什么用处。

关键词 iview webpack fonts 自行组合搜索。

上述过程失败后,询问了前端的朋友,给出了一些他的建议,后来还是失败了。然后开始怀疑自己的配置 loader 并没有生效。

开始查看源码:
在文件 ./node_modules/laravel-mix/src/builder/webpack-rules.js 搜索 ttf 看到 96 - 114 行的如下内容。

[file

](https://lccdn.phphub.org/uploads/images/201711/22/6324/l4KqpvoXJL.png)

立刻明白了。自己的配置因为 test 与 默认的不同。所以不会覆盖默认的配置。

所以进行了如下操作:
将该 rules 的 loader 段加入项目的 webpack.mix.js 中,并将 publicPath 修改为实际访问的地址 '/public/assets/main' + Config.resourceRoot

/**
 * webpack 配置
 */

mix.webpackConfig({
  output: {
    // 依据该路径进行编译以及异步加载
    publicPath: 'assets/main/',
    // 注意开发期间不加 hash,以免自动刷新失败
    chunkFilename: `js/chunk[name].${ mix.inProduction() ? '[chunkhash].' : '' }js`
  },

  plugins: [
    // 不打包 moment.js 的语言文件以减小体积
    new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/),
  ],

  module: {
    rules: [
      {
        test: /\.(woff2?|ttf|eot|svg|otf)$/,
        loader: 'file-loader',
        options: {
          publicPath: '/public/assets/main' + Config.resourceRoot
        }
      }
    ]
  }
})

重写 运行 yarn prod 后,控制台错误消失。问题解决。

附上第一次成功试验的完整文件内容

更完美的做法在文章尾部

const fs = require('fs')
const mix = require('laravel-mix')
const path = require('path')
const webpack = require('webpack')

/**
 * webpack 配置
 */

mix.webpackConfig({
  output: {
    // 依据该路径进行编译以及异步加载
    publicPath: 'assets/main/',
    // 注意开发期间不加 hash,以免自动刷新失败
    chunkFilename: `js/chunk[name].${ mix.inProduction() ? '[chunkhash].' : '' }js`
  },

  plugins: [
    // 不打包 moment.js 的语言文件以减小体积
    new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/),
  ],

  module: {
    rules: [
      {
        test: /\.(woff2?|ttf|eot|svg|otf)$/,
        loader: 'file-loader',
        options: {
          publicPath: '/public/assets/main' + Config.resourceRoot
        }
      }
    ]
  }
})

/**
 * SPA 资源编译
 */

mix
  .setPublicPath(path.normalize('Demo/public/assets/main'))
  .options({
    processCssUrls: false
  })
  .js('resources/assets/main/js/app.js', 'js')
  .extract([
    'axios',
    'lodash',
    'vue',
    'vue-router',
  ])
  .autoload({
    vue: ['Vue']
  })

/**
 * 发布时文件名打上 hash 以强制客户端更新
 */

if (mix.inProduction()) {
  mix.version()
} else {
  mix.disableNotifications()
}

// 加载 .env 中 browserSync proxy 的配置
let paths = fs.readFileSync('.env', 'utf8').match(/BROWSERSYNC_PROXY=\S*/)
let proxy = paths ? paths[0].split('=')[1] : 'server.test'

/**
 * 本地调试 dev-server 配置
 */

mix.browserSync({
  proxy,
  files: [
    'resources/assets/js/**/*.js',
    'Demo/Site/View/**/*.tpl.php',
  ]
})

更完美的做法

也许你看到了如下配置项:setPublicPath 就猜想有没有 setResourcePath

答案是有的:在源码文件 node_modules/laravel-mix/src/Api.js 中搜索 setResourcePath 来到 400-409 行,看到如下内容:

[file

](https://lccdn.phphub.org/uploads/images/201711/22/6324/w4MkUcJGOu.png)

说明我们可以直接用 setResourcePath 来设置我们的资源路径

mix.setResourceRoot('/public/assets/main/') 请不要漏掉最前面与最后一级文件的 /,原因自行试验

附上最终文件的完整文件内容

const fs = require('fs')
const mix = require('laravel-mix')
const path = require('path')
const webpack = require('webpack')

/**
 * webpack 配置
 */

mix.webpackConfig({
  output: {
    // 依据该路径进行编译以及异步加载
    publicPath: 'assets/main/',
    // 注意开发期间不加 hash,以免自动刷新失败
    chunkFilename: `js/chunk[name].${ mix.inProduction() ? '[chunkhash].' : '' }js`
  },

  plugins: [
    // 不打包 moment.js 的语言文件以减小体积
    new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/),
  ]
})

mix.setResourceRoot('/public/assets/main/')

/**
 * SPA 资源编译
 */

mix
  .setPublicPath(path.normalize('Demo/public/assets/main'))
  .options({
    processCssUrls: false
  })
  .js('resources/assets/main/js/app.js', 'js')
  .extract([
    'axios',
    'lodash',
    'vue',
    'vue-router',
  ])
  .autoload({
    vue: ['Vue']
  })

/**
 * 发布时文件名打上 hash 以强制客户端更新
 */

if (mix.inProduction()) {
  mix.version()
} else {
  mix.disableNotifications()
}

// 加载 .env 中 browserSync proxy 的配置
let paths = fs.readFileSync('.env', 'utf8').match(/BROWSERSYNC_PROXY=\S*/)
let proxy = paths ? paths[0].split('=')[1] : 'server.test'

/**
 * 本地调试 dev-server 配置
 */

mix.browserSync({
  proxy,
  files: [
    'resources/assets/js/**/*.js',
    'Demo/Site/View/**/*.tpl.php',
  ]
})

附上 laravel-mix 文档

https://github.com/JeffreyWay/laravel-mix/tree/master/docs#readme

Study hard and make progress every day. Study hard and make progress every day.


Original url: Access

Created at: 2018-10-10 18:51:20

Category: default

Tags: none

请先后发表评论
  • 最新评论
  • 总共0条评论