• nuxt.js-ant-design-vue配置踩坑日记


    最近开发一个带seo以及部分后台功能的项目,nuxt作为vue ssr框架可以非常好的完成这个需求,这里我选择了ant-design-vue作为UI组件库。

    以下是踩坑的一些记录 :

    首先介绍一下项目情况和需求:

    • Nuxt.js是一个 Vue.js 通用框架,预设了使用 Vue.js开发SSR的各种配置。项目中使用的是SSR模式,因此首屏是由服务端完成渲染
    • 项目仅用到少数的UI组件,因此我们希望使用按需加载组件,以减少网络开销。

    1. 按需加载引入组件

    首先我们移除掉 nuxt.config.js 

    1. {
    2.    css: ['ant-design-vue/dist/antd.css'],
    3.    // 这里会全局引入所有样式,不是我们所希望的按需加载
    4. }


    参考官方文档antd-vue # 按需加载:

    1. // 同时参考 Nuxt-cli 创建项目时 创建的 plugin/antd-ui.js
    2. import Vue from 'vue'
    3. import Button from 'ant-design-vue/lib/button';
    4. import 'ant-design-vue/lib/button/style'; // 或者 ant-design-vue/lib/button/style/css 加载 css 文件
    5. Vue.use(Button.name, Button)

    编译未通过,提示错误:

    1. // https://github.com/ant-design/ant-motion/issues/44
    2. .bezierEasingMixin();
    3. ^
    4. Inline JavaScript is not enabled. Is it set in your options?

    根据报错所提供的信息,less升级到3.0 后,需要 less-loader配置一个功能,才能正常使用:

    1. // nuxt.config.js
    2. {
    3.   build: {
    4.     loaders: {
    5.       less: {
    6.         javascriptEnabled: true
    7.       }
    8.     }
    9.   }
    10. }

    编译通过,打开页面,返回500,提示:

    编译能通过,说明代码编译没有问题,但是server端执行时出现了错误。尝试注释掉plugin/antd-ui.js引入样式文件这行 import 'ant-design-vue/lib/button/style'; ,server首屏渲染能够正常启动,但引入的button组件样式丢失。

    打开 ant-design-vue/lib/button/style/index.js 查看:

    1. 'use strict';
    2. require('../../style/index.less');
    3. require('./index.less');
    4. // ant-design-vue/es/button/style/index.js
    5. import '../../style/index.less';
    6. import './index.less';

    可以看到,antd-vue为生产环境提供了两种模块的代码。为了tree-shaking 我们优先选择 es 模块。

    补充知识:现在的webpack@4+ 支持识别项目 packge.json module字段,使用ESModule的依赖更好的支持构建中的tree-shaking。

    修改代码为 es/button/...,编译通过,但页面仍抛出一500服务端错误:

    根据错误提示cannot use import statement和es包使用的ESModule语法,猜测服务端侧渲染页面时语法出错,Node.js 不能直接识别 .js文件内的ESModule语法。

    1. // .nuxt.config.js
    2. {
    3. plugins: [
    4. {
    5. src: '@/plugins/antd-ui',
    6. mode: 'client' // 仅 客户端使用plugin
    7. }
    8. ]
    9. }


    页面正常加载,但Vue.js 给出了错误提示

    此时,我们再将plugin代码替换回lib以及移除mode: 'client ,错误又回到了最开始的 invalid or unexpected token

    搜索Nuxt官方文档:

    如果要使用Babel与特定的依赖关系进行转换,你可以在build.transpile中添加它们,transpile中的选项可以是字符串或正则表达式对象,用于匹配依赖项文件名。

    添加配置:

    1. { // nuxt.config.js
    2.   build: {
    3.     transpile: [/ant-design-vue/]
    4.   }
    5. }

    终于,服务端渲染正常,样式也正常加载。接着引入 ant-design-vue官方推荐使用的插件babel-plugin-import

    1. // nuxt.config.js
    2. {
    3.   build: {
    4.     babel: {
    5.       plugins: [
    6.         [
    7.           'import',
    8.           {
    9.             libraryName: 'ant-design-vue',
    10.             libraryDirectory: 'es',
    11.             // 选择子目录 例如 es 表示 ant-design-vue/es/component
    12.             // lib 表示 ant-design-vue/lib/component
    13.            
    14.             style: true
    15.             // 默认不使用该选项,即不导入样式 , 注意 ant-design-vue 使用 js 文件引入样式
    16.             // true 表示 import  'ant-design-vue/es/component/style'
    17.             // 'css' 表示 import 'ant-design-vue/es/component/style/css'
    18.           }
    19.         ]
    20.       ]
    21.     }
    22.   }
    23. }
    24. // plugins/antd-ui.js
    25. import Vue from 'vue'
    26. import { Button } from 'ant-dsign-vue'
    27. // 这时,可以通过 简写的方式引入样式和组件
    28. Vue.use(Button)


    2. pages目录内引入组件

     

    上图是在pages/index.vue内引入组件,npm run build && npm run start 执行后的线上环境,可以看到样式在刷新首屏时,会看到闪烁的现象,这里出现的问题在于入口文件并不包含组件,而是异步引入的,从编译结果上也可以看到 610kb 的包对应的chunk vendors.pages/index ,并不在entrypoint内,默认情况下Nuxt.js 路由页面已经被分配为dynamic import,同时style是通过js设置到style上的,而不是单独打包出来。经过测试,css单独打包后,UI组件仍是单独分包,即便是单独打包出来,依然会有按需加载的问题,首屏仍会闪烁。

    build result

    因此,如果组件被大多数页面使用,推荐在 plugin内注册,或者通过 nuxt.config.js的css相关文件直接引入对应的组件样式,同时关闭babel-import-plugin 的 style选项。 (吐槽一句,iView只能引入单一全局样式,不能按需加载样式,1.5m的大小非常恐怖)

    除此以外,可以考虑配置webpacksplitchunks配置,实现自己的需求。

    3. 解决antd-icon 过大(传统艺能

    前面生产环境的包可以发现,只使用了一个Button,却打包了600kb的依赖,检查后发现是引入了@ant-design/icon 包。

    参考: https://github.com/HeskeyBaozi/reduce-antd-icons-bundle-demo

    1. { // nuxt.config.js
    2.   build: {
    3.     extend(config, ctx) {
    4.       config.resolve.alias['@ant-design/icons/lib/dist$'] = path.resolve(__dirname, './assets/icon/antd-icon.js') // 引入需要的
    5.     }
    6.   }
    7. }


    题外话

    “按需引入”

  • 相关阅读:
    Docker设置开机自启动
    【计算机视觉 | 分割】SAM 升级版:HQ-SAM 的源代码测试(含测试用例)
    通过Keil如何查看MCU的RAM与ROM使用情况
    [python 刷题] 242 Valid Anagram
    TCP特性的滑动窗口,流量控制
    HomeAssistant——Intrgration开发
    剑指 Offer 35. 复杂链表的复制
    Github 注册
    【教3妹学算法-每日1题】设计有序流
    【Mysql】基于MySQL协议的抓包工具
  • 原文地址:https://blog.csdn.net/weixin_42232156/article/details/126140218