【问题标题】:Extract CSS from SCSS and deferred lazy load in React app从 SCSS 中提取 CSS 并在 React 应用程序中延迟延迟加载
【发布时间】:2018-09-30 19:33:59
【问题描述】:

我有一些 SCSS 主题文件,我想将它们提取为 CSS 文件,然后将它们加载到页面中。我希望能够使用contenthash 进行长期缓存。

由于我使用的是 Webpack 4,所以我也在使用 mini-css-extract-plugin。我开始在我的 webpack 配置中创建 splitChunks。

// webpack.config.js
module.exports = {
  plugins: [
      new MiniCssExtractPlugin({
      // Options similar to the same options in webpackOptions.output
      // both options are optional
      filename: "[name].[contenthash].css",
      chunkFilename: "[id].[contenthash].css"
    })
  ],
  optimization: {
    splitChunks: {
      cacheGroups: {
        'vendor': {
            // custom commons chunk for js
        },
        'theme-a': {
            test: /theme-a.\scss/,
        },
        'theme-b': {
            test: /theme-b.\scss/,
        },
        // more themes
      }
    }
  }
  module: {
    rules: [
      {
        test: /\.scss$/,
        use: [
          MiniCssExtractPlugin.loader,
          "css-loader",
          "sass-loader"
        ]
      }
    ]
  }
}

然后我在我的应用程序中尝试了dynamically importing css:

// app.js
class App extends React.Component {
  // constructor

  login(themeName) {
    import(/* webpackChunkName: "`${themeName}`" */ `./path/to/${themeName}.scss`).then(theme => {
      // do something with `theme`
    }
  }

  // other stuff
}

我需要能够在 login() 中动态加载该 css 文件,但我不确定当它生成 [contenthash] 时如何引用它。

TLDR: 有没有一种既能提取 CSS 又能导入引用的 CSS 包以便稍后延迟加载的好方法?我没有绑定到mini-css-extract-plugin

编辑:创建了一个mini-css-extract-plugin 问题here

【问题讨论】:

    标签: css reactjs webpack lazy-loading


    【解决方案1】:

    我的解决方案最终使用了extract-text-webpack-plugin。我的配置现在看起来像这样:

    // webpack.config.js
    const ExtractTextPlugin = require('extract-text-webpack-plugin');
    const ExtractThemeA = new ExtractTextPlugin({ filename: 'themeA.[hash].css', allChunks: true});
    
    module.exports = {
      plugins: [
          ExtractThemeA,
          // more plugins for other css files
      ],
      optimization: {
        splitChunks: {
          cacheGroups: {
            // Note: No changes to splitChunks
            'vendor': {
                // custom commons chunk for js
            }
        }
      }
      module: {
        rules: [
          {
            test: /theme-a\.scss$/,
            use: ExtractThemeA.extract([ 'css-loader', 'sass-loader' ])
          },
          // more module rules for each css file needed
        ]
      }
    }
    

    然后,这些块可以通过我的HtmlWebpackPlugin 中的文件名获得:

    <!-- HtmlWebpackPlugin Template -->
    <script>
    // provides me with an array of file name strings
    var themesManifest = <%= htmlWebpackPlugin.files.css %>
    </script>
    

    【讨论】:

      【解决方案2】:

      对不起,我的理解有误,

      您可能只需制作两个不同的 scss 文件并根据需要导入它们。 theme.scss admin.scss 或类似

      这就是我现在在 React 中做 scss 的方式

      在 App.js 中

      import styles from '../../stylesheet/main.scss'
      // could be as well
      import styles1 from '../../stylesheet/theme.scss' // some file
      import styles2 from '../../stylesheet/admin.scss' // some other file
      
      const App = () => {
        <div className={styles.action_feed} >{ content }</div>
      } 
      

      在 main.scss 中

      .action_feed {
        position: fixed;
        width: 350px;
        height: auto;
        max-height: 100%;
        max-width: 100%;
        top: 0;
        left: 0;
        z-index: 9999;
      }
      

      我认为你也可以这样做

      const themeName = 'main'
      import(`./stylesheet/${themeName}.scss`, (css) => {
        // meaby set this to state? not quite sure how should properly handle
        // dynamically imported css
        this.setState({ css: css.action_feed })
      
        // or possible this way. I have done some non-React dom manipulation
        // this way before
        document.querySelector('body').classList.add(css.action_feed)
      })
      
      <div className={this.state.css}>{ content }</div>
      

      您可能还应该查看 React 的新 Refs API。它可能会给你一些很好的灵活性,可以将className-attr 赋予所需的元素。

      设置为splitChunks.chunksall 可以工作,但我认为在这种情况下无论如何

      【讨论】:

      • 我不担心我的 JS 没有被分块,而是这些单独的主题 css 文件。我需要将这些文件提取并加载到login()
      • 我很欣赏您的回复,但同样不是我想要的。我需要提取css(用于http缓存目的)并动态注入login()上的页面。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-05-30
      • 1970-01-01
      • 1970-01-01
      • 2015-01-11
      • 2015-09-01
      相关资源
      最近更新 更多