alibaba / rax

🐰 Rax is a progressive framework for building universal application. https://rax.js.org
Other
8k stars 627 forks source link

[Question]如何正确使用@unocss/webpack #2321

Closed xmsz closed 2 years ago

xmsz commented 2 years ago

背景

报错

ERR! CONFIG Failed to load webpack config. ERR! Invalid configuration object. Webpack has been initialized using a configuration object that does not match the API schema.

wjq990112 commented 2 years ago

这个可能需要自定义 build.plugin.js 才能做了,因为 UnoCSS 的 Webpack Plugin 导出的方式比较特殊,是 default 导出的

wjq990112 commented 2 years ago

我给你一个示例,可以试一下:

// build.plugin.js
const UnoCSS = require('@unocss/webpack').default;

module.exports = ({ onGetWebpackConfig }) => {
  onGetWebpackConfig((config) => {
    config
    .plugin('UnoCSSPlugin')
    .use(UnoCSS)
    .end();
  });
};
// build.json
{
  "plugins": ["./build.plugin.js"]
}
wjq990112 commented 2 years ago

可以试一下,然后现在 Rax 也能比较轻松地使用 Tailwind CSS 和 WindiCSS,欢迎体验!

xmsz commented 2 years ago

可以试一下,然后现在 Rax 也能比较轻松地使用 Tailwind CSS 和 WindiCSS,欢迎体验!

牛逼

xmsz commented 2 years ago
const UnoCSS = require('@unocss/webpack').default;
const presetUno = require('@unocss/preset-uno').default;

module.exports = ({ onGetWebpackConfig }) => {
  onGetWebpackConfig((config) => {
    config
      .plugin('UnoCSSPlugin')
      .use(UnoCSS({ presets: [presetUno()] }))
      .end();
  });
};

但是使用的时候

<View className="ma4"></View>

没有效果 构建出来也没有 我不知道我漏了哪步

wjq990112 commented 2 years ago

示例可能有点问题,我没有尝试,具体用法可以看下 Webpack Chain 是怎么配置 Webpack Plugin 的,按照 Webpack Chain 的方式修改 config 就可以

wjq990112 commented 2 years ago

我看了你的代码,我理解是传参数的方式不正确,Webpack Chain 给 Webpack Plugin 传参数的时候不能直接传入 UnoCSS 里,而是要作为第二个参数,像这样:

const UnoCSS = require('@unocss/webpack').default;
const presetUno = require('@unocss/preset-uno').default;

module.exports = ({ onGetWebpackConfig }) => {
  onGetWebpackConfig((config) => {
    config
      .plugin('UnoCSSPlugin')
-     .use(UnoCSS({ presets: [presetUno()] }))
+     .use(UnoCSS, [{ presets: [presetUno()] }])
      .end();
  });
};
xmsz commented 2 years ago

@wjq990112

我又尝试了一下

// build.plugin.js
const UnoCSS = require('@unocss/webpack').default;
const { presetUno } = require('@unocss/preset-uno');

module.exports = ({ onGetWebpackConfig }) => {
  onGetWebpackConfig((config) => {
    config
      .plugin('UnoCSSPlugin')
      .use(UnoCSS, [
        {
          presets: [presetUno()],
        },
      ])
      .end();
  });
};

// app.tsx
import 'uno.css';

情况一:没有实时更新_virtual_uno.css文件

需要重新构建才生效 或者手动rm -rf ./node_modules/.cache


情况二:内容经常变得不正确

变成

.static{position:static;}.m374\.635{margin:93.65875rem;}.flex{display:flex;}.tab-\$\{index\}{-moz-tab-size:var(--\{index\});-o-tab-size:var(--\{index\});tab-size:var(--\{index\});}

怀疑是应该是压缩插件导致,但不确定


情况三:rpx单位没有转换

.h-100rpx {
  height: 100rpx
}

最终还是rpx而不是编译后

wjq990112 commented 2 years ago

@xmsz

情况一:这个可能是 UnoCSS Webpack Plugin 的 bug,可以反馈一下,node_modules/.cache 文件夹是 Webpack 5 的缓存文件,如果更新对应的模块没能实时更新缓存,应该是有 bug 的。

情况二:看起来像是变量没有替换成功,暂时不清楚是不是也是 UnoCSS Webpack Plugin 的 bug。

情况三:rpx 单位的处理是在 postcss-plugin-rpx2vw 中做的处理,而 UnoCSS 直接使用的 Webpack Plugin,rpx 单位并没有通过 postcss-plugin-rpx2vw 处理,因此 rpx 未被转换的情况符合预期。

xmsz commented 2 years ago

情况一:我用简易webpack项目会实时更新(不过简易项目和普通vite项目都是直接注入在页面style中所以看不到_virtual_uno.css是否有变化) 不确定是不是其他配置影响


const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const UnoCSS = require('@unocss/webpack').default;
const { presetUno } = require('@unocss/preset-uno');

module.exports = (env, { mode = 'production' }) => {
  const isDev = mode === 'development';

  return {
    mode,
    module: {
      rules: [
        {
          test: /\.js$/,
          exclude: /(node_modules)/,
          use: [
            {
              loader: 'babel-loader',
              options: {
                presets: ['@babel/preset-react'],
              },
            },
          ],
        },
        {
          test: /\.css$/,
          use: [
            isDev ? 'style-loader' : MiniCssExtractPlugin.loader,
            'css-loader',
          ],
        },
      ],
    },
    plugins: [
      new UnoCSS({
        include: [/\.js$/],
        exclude: [/node_modules/],
        presets: [presetUno()],
      }),
      !isDev && new MiniCssExtractPlugin(),
      new HtmlWebpackPlugin({
        template: './src/index.html',
      }),
    ].filter(Boolean),
  };
};

有点麻烦

xmsz commented 2 years ago

问题三:https://github.com/unocss/unocss/issues/386 确实不会先经过postcss 很蛋疼

xmsz commented 2 years ago

问题一:https://windicss.org/integrations/webpack.html 我尝试windicss也是没有实时更新 需要重新编译

然后如果用webpack插件 windicss会经过postcss 还是挺好的 如果用postcss插件则 windcss则还是需要考虑顺序问题

但都是需要重新编译才会生成

wjq990112 commented 2 years ago

可能使用 Webpack Plugin 扫描样式并生成的这个逻辑在 rpx 的体系下都存在一点问题,试下用 WindiCSS 的 PostCSS 模式,或者 Tailwind CSS,因为 Tailwind CSS 本质是一个 postcss 插件。

wjq990112 commented 2 years ago

如果需要关闭 Webpack 缓存,可以试下带上 --force 参数启动,关闭 Webpack 的缓存之后看下是否还存在无法实时更新的问题?

xmsz commented 2 years ago

可能使用 Webpack Plugin 扫描样式并生成的这个逻辑在 rpx 的体系下都存在一点问题,试下用 WindiCSS 的 PostCSS 模式,或者 Tailwind CSS,因为 Tailwind CSS 本质是一个 postcss 插件。

我用windCSS的postCSS模式,rpx没有转换,估计是顺序问题

wjq990112 commented 2 years ago

我看下 WindiCSS 的 PostCSS 插件是怎么实现的,这个问题应该跟插件实现有关系。

xmsz commented 2 years ago

--force

rax-app start --force

我是这样写 + postcss插件 还是没有效果

wjq990112 commented 2 years ago

理论上来说确实跟 PostCSS 插件的顺序有关系,稍等我验证一下给你一个解决方案。

wjq990112 commented 2 years ago
// build.plugin.js
const WindiCSS = require('postcss-windicss');

const checkPostcssLoader = (config, ruleName) =>
  config.module.rules.has(ruleName) && config.module.rule(ruleName).uses.has('postcss-loader');

module.exports = ({ onGetWebpackConfig }) => {
  onGetWebpackConfig((config) => {
    const rules = ['css', 'css-module', 'css-global'];

    rules.forEach((rule) => {
      if (checkPostcssLoader(config, rule)) {
        config.module
          .rule(rule)
          .use('postcss-loader')
          .tap((options) => ({
            ...options,
            postcssOptions: {
              ...options.postcssOptions,
              plugins: [WindiCSS, ...options.postcssOptions.plugins],
            },
          }));
      }
    });
  });
};
xmsz commented 2 years ago
// build.plugin.js
const WindiCSS = require('postcss-windicss');

const checkPostcssLoader = (config, ruleName) =>
  config.module.rules.has(ruleName) && config.module.rule(ruleName).uses.has('postcss-loader');

module.exports = ({ onGetWebpackConfig }) => {
  onGetWebpackConfig((config) => {
    const rules = ['css', 'css-module', 'css-global'];

    rules.forEach((rule) => {
      if (checkPostcssLoader(config, rule)) {
        config.module
          .rule(rule)
          .use('postcss-loader')
          .tap((options) => ({
            ...options,
            postcssOptions: {
              ...options.postcssOptions,
              plugins: [WindiCSS, ...options.postcssOptions.plugins],
            },
          }));
      }
    });
  });
};

我用新项目 提示"PostCSS plugin postcss-windicss requires PostCSS 8."

旧项目顺序还是不对(可能是没更新,正常应该和新项目一样的提示)

wjq990112 commented 2 years ago

PostCSS 8 的问题有点难受,建议还是用 Tailwind CSS 吧,有 PostCSS 7 的 compat。

xmsz commented 2 years ago

PostCSS 8 的问题有点难受,建议还是用 Tailwind CSS 吧,有 PostCSS 7 的 compat。

Tailwind还需要额外插件把px转成rpx