// ant-design-vue/lib/button/style/index.js
'use strict';
require('../../style/index.less');
require('./index.less');
// ant-design-vue/lib/button/style/css.js
'use strict';
require('../../style/index.css');
require('./index.css');
// ant-design-vue/es/button/style/index.js
import '../../style/index.less';
import './index.less';
// ant-design-vue/es/button/style/css.js
import '../../style/index.css';
import './index.css';
可以看到,antd-vue 将样式文件通过js引入,分别提供了less(定制主题)/css两种样式引入,且提供了两种模块格式的代码。
补充知识:现在的webpack@4+ 支持识别项目 packge.json module 字段,使用ESModule的依赖更好的支持构建中的tree-shaking。
尝试分别引入4个样式的入口的js文件,编译通过,但会得到三种500报错:
import 'ant-design-vue/es/button/style/css.js'
import 'ant-design-vue/es/button/style/index.js'
// Cannot use import statement outside a module
import 'ant-design-vue/lib/button/style/index.js'
// Invalid or unexpected token
import 'ant-design-vue/lib/button/style/css.js'
// Unexpected token '{'
直接引入 css/less文件,编译通过,服务端不再报错,正常渲染:
import 'ant-design-vue/lib/button/style/index.less'
// or
import 'ant-design-vue/lib/button/style/index.css'
最后我们尝试,不引入样式,修改组件引入 es/button/... ,编译通过,但仍抛出500服务端错误Cannot use import statement outside a module :
image.png
根据前面的测试,猜测服务端侧渲染页面时出现了语法出错:
-
Nuxt.js 默认情况下,没有将node_modules 引入的依赖正确编译到server侧,依赖内包含了只能被webpack 识别的 import 'xxx.css' 或,require('xxx.less') ,导致server代码执行时错误。 -
Nuxt.js 默认情况下,没有将ESModule 语法编译到server侧。
接着测试:
// .nuxt.config.js
{
plugins: [
{
src: '@/plugins/antd-ui',
mode: 'client' // 仅 客户端使用plugin
}
]
}
页面正常加载,样式渲染成功,确认了之前的猜测,但Vue.js 给出了错误提示:
image.png
搜索Nuxt [官方文档](
):
如果要使用Babel与特定的依赖关系进行转换,你可以在build.transpile 中添加它们,transpile 中的选项可以是字符串或正则表达式对象,用于匹配依赖项文件名。
移除plugin的mode: 'client' ,添加配置:
{ // nuxt.config.js
build: {
transpile: [/ant-design-vue/]
}
}
终于,服务端渲染正常,样式也正常加载。
根据前面的尝试结果,我们可以考虑为client/server,添加不同的plugin用于引入组件,或者使用transplie 选项将node_modules 引入的组件,纳入babel 编译。这里是一个取舍问题:
-
ui库提供了es语法模块更好的支持tree shaking ,但我们又需要CommonJS 模块语法的依赖来支持Node.js 。 -
如果将库二次babel编译,库可能已经经过了babel编译,可能同样会导致依赖引入变大。
其次,transpile 选项应该不止包括babel ,而是将node_modules 引入的依赖都纳入到编译范围,对于引入其他模块类型文件(import 'xxxx.less' )也做了处理(通过webpack ),否则引入样式文件都会导致server端执行过程报错。
2. 引入babel-plugin-import
接着引入 ant-design-vue 官方文档上使用的插件[babel-plugin-import](
)
// nuxt.config.js
{
build: {
babel: {
plugins: [
[
'import',
{
libraryName: 'ant-design-vue',
libraryDirectory: 'es',
// 选择子目录 例如 es 表示 ant-design-vue/es/component
// lib 表示 ant-design-vue/lib/component
style: true
// 默认不使用该选项,即不导入样式 , 注意 ant-design-vue 使用 js 文件引入样式
// true 表示 import 'ant-design-vue/es/component/style'
// 'css' 表示 import 'ant-design-vue/es/component/style/css'
}
]
]
}
}
}
// plugins/antd-ui.js
import Vue from 'vue'
import { Button } from 'ant-dsign-vue'
// 这时,可以通过 简写的方式引入样式和组件
Vue.use(Button)
3. pages 目录内引入组件
flash.gif
上图是仅在pages/index.vue 内引入组件,npm run build && npm run start 编译后的线上环境,可以看到样式在刷新首屏时,会看到闪烁的现象。这里出现的问题,原因在于入口文件并不包含页面内依赖的chunk,而是按需加载的,从编译结果上也可以看到 610kb 的包对应的chunk vendors.pages/index ,并不在entrypoint 内。
|