Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

关于异步css模块增加preload以防止页面闪烁的问题 #78

Closed
zcgzxg opened this issue Jul 12, 2021 · 11 comments
Closed

关于异步css模块增加preload以防止页面闪烁的问题 #78

zcgzxg opened this issue Jul 12, 2021 · 11 comments

Comments

@zcgzxg
Copy link

zcgzxg commented Jul 12, 2021

如题,是否在服务器渲染时,根据当前路由,对当前路由关联的异步加载的css文件增加preload?
我认为在webpack打包时,可以将关联关系记录下来,在服务器端渲染时根据引用关系增加css文件的preload.

@zhangyuang
Copy link
Owner

已经有了这个逻辑了啊

@zhangyuang
Copy link
Owner

1、你只能拿到页面的chunk name 不能拿到具体的异步模块,重复模块的 chunk
2、页面 的chunk preload 逻辑已经有了,异步模块重复模块的 chunk css preload 没有,也做不到。参考 http://doc.ssr-fc.com/docs/features$faq#%E4%BB%A3%E7%A0%81%E5%88%86%E5%89%B2%E5%B8%B8%E8%A7%81%E9%97%AE%E9%A2%98

@zhangyuang
Copy link
Owner

后续如果有更好的方案可以 reopen 本 issue

@zcgzxg
Copy link
Author

zcgzxg commented Jul 15, 2021

通过给splitChunks的name属性传递一个函数,就可以记录到页面关联的异步css文件
代码如下:

const cssManifest = {}

/**
 * @see [config document](http://doc.ssr-fc.com/docs/api$config)
 * @type {import('ssr-types').IConfig}
 */
const config = {
  chainBaseConfig: (chain) => {
    chain.module
      .rule('compile')
      .use('babel-loader')
      .tap((args) => {
        args.plugins = args.plugins || []
        args.plugins.push([
          'import',
          {
            libraryName: 'ant-design-vue',
            libraryDirectory: 'lib', // 这里一定要用 lib
            style: true // true 代表 style/index.js 会加载 less 类型的文件
          },
          'ant-design-vue'
        ])
        return args
      })
  },
  chainClientConfig: chain => {
    chain.optimization
      .splitChunks({
        chunks: 'async',
        minSize: 20000,
        minChunks: 1,
        maxAsyncRequests: 30,
        maxInitialRequests: 30,
        enforceSizeThreshold: 50000,
        name(module, chunks, cacheGroupKey) {
          const moduleFileName = module
            .identifier()
            .split('/')
            .reduceRight((item) => item)
          const allChunksNames = chunks.map((item) => item.name)
          const name = `${cacheGroupKey}-${allChunksNames.join('~')}`

          if (
            moduleFileName.endsWith('.css') ||
            moduleFileName.endsWith('.less')
          ) {
            cssManifest[name + '.css'] = allChunksNames
          }
          return name
        },
        cacheGroups: {
          vendors: {
            test: /[\\/]node_modules[\\/]/,
            priority: -10,
            reuseExistingChunk: true
          },
          common: {
            minChunks: 2,
            priority: -20,
            reuseExistingChunk: true
          }
        }
      })
      .end()

    chain.plugin('WriteCssManifest').use(
      class WriteCssManifest {
        apply(compiler) {
          compiler.hooks.done.tapAsync(
            'WriteCssManifest',
            (params, callback) => {
              console.log(cssManifest)
              // 将cssManifest定入文件
              callback()
            }
          )
        }
      }
    )
  }
}

module.exports = config

输出结果:

{
  'vendors-error~not-found.css': [ 'error', 'not-found' ],
  'vendors-error.css': [ 'error' ],
  'vendors-not-found.css': [ 'not-found' ],
  'common-error~not-found.css': [ 'error', 'not-found' ],
  'default-error~not-found.css': [ 'error', 'not-found' ]
}

asset-manifest.json

{
  "vendors-error~not-found.css": "/client/static/css/vendors-error~not-found.3a4b319b.chunk.css",
  "vendors-error~not-found.js": "/client/static/js/vendors-error~not-found.f158e1c4.chunk.js",
  "Page.css": "/client/static/css/Page.9b4ee7a2.chunk.css",
  "Page.js": "/client/static/js/Page.09ca0ac9.chunk.js",
  "error.js": "/client/static/js/error.50cbdb75.chunk.js",
  "not-found.js": "/client/static/js/not-found.2b4040ec.chunk.js",
  "runtime~Page.js": "/client/static/js/runtime~Page.4e272446.js"
}

示例地址:
git@code.aliyun.com:tn_zhuxg/vue3-ssr.git

@zhangyuang
Copy link
Owner

emmm试了下我没看出你要解决的问题是什么。你在什么情况下会出现闪烁呢。建议扫码加入微信群交流

@zhangyuang
Copy link
Owner

and 你的仓库并没有权限打开

@zhangyuang
Copy link
Owner

and 解决 antd 样式闪烁请参考http://doc.ssr-fc.com/docs/features$faq#%E5%B0%86%20css%20%E6%8F%90%E5%8F%96%E4%B8%BA%E4%B8%80%E4%B8%AA%E5%A4%A7%E6%96%87%E4%BB%B6
and 你不需要额外添加 babel-plugin-import 配置

@zcgzxg
Copy link
Author

zcgzxg commented Jul 15, 2021

我不要将css提取成一个大文件,我想要将公共css分割出去,但是分割出去的css是异步加载的,会出现闪烁.
我想的解决办法是根据请求的页面找到对应的异步css,将它加到preload中

 <link rel="preload" href="page-a~page-b.common.css" as="style">

@zhangyuang
Copy link
Owner

如果是你分割的的css是多个页面重复的那肯定是异步的啊,自己用 extraCssOrder 手动引入。没看出你这种切割的必要性,切不切割都得加载完这个文件页面才是正常的。

@zcgzxg
Copy link
Author

zcgzxg commented Jul 15, 2021

我觉得对于需要异步加载css的人来说,能够通过preload改善页面闪烁是有价值的。
对于复杂项目将所有初次渲染时用到的css打包成一个大文件也不合理。

@zcgzxg
Copy link
Author

zcgzxg commented Jul 15, 2021

每个页面需要的css文件不一样,extraCssOrder并不能根据路由决定加载什么css

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants