【问题标题】:CSS Modules export CSSes as <style> tag in head tag with disabled sourceMapCSS 模块将 CSS 导出为 head 标记中的 <style> 标记,并禁用 sourceMap
【发布时间】:2018-10-04 19:57:13
【问题描述】:

我正在写ReactServer Side RenderingRouter4HelmetCSS Modules 样板,一切都很棒,但有一件事伤害了我的灵魂:

先看我的webpack.production.config.js:

const path = require('path');
const webpack = require('webpack');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const StatsPlugin = require('stats-webpack-plugin');
const OptimizeCssAssetsPlugin = require('optimize-css-assets-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');

const distDir = path.join(__dirname, 'dist');
const srcDir = path.join(__dirname);

module.exports = [
    {
        name: 'client',
        target: 'web',
        entry: `${srcDir}/client.jsx`,
        output: {
            path: distDir,
            filename: 'client.js',
            publicPath: distDir,
        },
        resolve: {
            extensions: ['.js', '.jsx']
        },
        module: {
            rules: [
                {
                    test: /\.(js|jsx)$/,
                    exclude: /(node_modules\/)/,
                    use: [
                        {
                            loader: 'babel-loader',
                        }
                    ]
                },
                {
                    test: /\.scss$/,
                    use: [
                        {
                            loader: 'style-loader',
                        },
                        {
                            loader: 'css-loader',
                            options: {
                                modules: true,
                                importLoaders: 1,
                                localIdentName: '[hash:base64:10]',
                                sourceMap: false,
                            }
                        },
                        {
                            loader: 'sass-loader'
                        }
                    ]
                }
            ],
        },
        plugins: [
            new webpack.DefinePlugin({
                'process.env': {
                    NODE_ENV: '"production"'
                }
            }),
            new CleanWebpackPlugin(distDir),
            new webpack.optimize.UglifyJsPlugin({
                compress: {
                    warnings: false,
                    screw_ie8: true,
                    drop_console: true,
                    drop_debugger: true
                }
            }),
            new webpack.optimize.OccurrenceOrderPlugin(),
        ]
    },
    {
        name: 'server',
        target: 'node',
        entry: `${srcDir}/server.jsx`,
        output: {
            path: distDir,
            filename: 'server.js',
            libraryTarget: 'commonjs2',
            publicPath: distDir,
        },
        resolve: {
            extensions: ['.js', '.jsx']
        },
        module: {
            rules: [
                {
                    test: /\.(js|jsx)$/,
                    exclude: /(node_modules\/)/,
                    use: [
                        {
                            loader: 'babel-loader',
                        }
                    ]
                },
                {
                    test: /\.scss$/,
                    use: ExtractTextPlugin.extract({
                        fallback: "isomorphic-style-loader",
                        use: [
                            {
                                loader: 'css-loader',
                                options: {
                                    modules: true,
                                    importLoaders: 1,
                                    localIdentName: '[hash:base64:10]',
                                    sourceMap: false
                                }
                            },
                            {
                                loader: 'sass-loader'
                            }
                        ]
                    })
                }
            ],
        },
        plugins: [
            new ExtractTextPlugin({
                filename: 'styles.css',
                allChunks: true
            }),
            new OptimizeCssAssetsPlugin({
                cssProcessorOptions: { discardComments: { removeAll: true } }
            }),
            new StatsPlugin('stats.json', {
                chunkModules: true,
                modules: true,
                chunks: true,
                exclude: [/node_modules[\\\/]react/],
            }),
        ]
    }
];

这是我的template.js 文件,服务器使用它来构建基本的HTML

export default ({ markup, helmet }) => {
    return `<!DOCTYPE html>
            <html ${helmet.htmlAttributes.toString()}>
                <head>
                    ${helmet.title.toString()}
                    ${helmet.meta.toString()}
                    ${helmet.link.toString()}
                </head>
                <body ${helmet.bodyAttributes.toString()}>
                    <div id="root">${markup}</div>
                    <script src="/dist/client.js" async></script>
                </body>
            </html>`;
};

就像我写的一样,我将sourceMap设置为false,所以所有样式都加载为&lt;style&gt;标签内的&lt;head&gt;标签。

如果我将soureMap设置为true&lt;link&gt;标签出现在&lt;head&gt;标签内,即使它不是服务器端,并且有一个奇怪的blob url用于加载CSS

实际上我想在head标签内直接指向styles.css的服务器端链接标签,我该怎么做?

我的整个项目都在THIS LINK

它没有很多代码,小而简单,它只是一个简单的样板。 看看

【问题讨论】:

    标签: reactjs webpack server-side-rendering css-modules react-helmet


    【解决方案1】:

    对于生产版本,在 client 配置中,您不使用样式加载器。您需要改用extract-text-webpack-plugin。您在 server 构建配置中正确执行了此操作。但是这个配置不应该在你的服务器构建中,因为在服务器的源代码中,你永远不会使用 (s)css 文件。

    {
      test: /\.scss$/,
      use: ExtractTextPlugin.extract({
         fallback: 'style-loader',
         use: [
            {
               loader: 'css-loader',
               options: {
                  modules: true,
                  localIdentName: '[hash:base64:10]',
               }
            },
            {
               loader: 'sass-loader'
            }
         ]
      })
    }
    ...
    plugins: [
       new ExtractTextPlugin({
          filename: 'styles.css'
       }),
    ]
    

    将此添加到您的 client 构建配置中。

    link={[{rel: "stylesheet", href: "/dist/styles.css"}]}
    

    并添加一个link 属性到您的App.jsx 以在您的&lt;head&gt; 标记中加载一个&lt;link&gt; 标记。

    所以你的App.jsx 渲染方法变成了:

    render() {
            return (
                <div>
                    <Helmet
                        htmlAttributes={{lang: "en", amp: undefined}} // amp takes no value
                        titleTemplate="%s | React App"
                        titleAttributes={{itemprop: "name", lang: "en"}}
                        meta={[
                            {name: "description", content: "Server side rendering example"},
                            {name: "viewport", content: "width=device-width, initial-scale=1"},
                        ]}
                        link={[{rel: "stylesheet", href: "/dist/styles.css"}]}/*ADD THIS*/
                    />
                    <Switch>
                        <Route exact path='/' component={Homepage}/>
                        <Route path="/about" component={About}/>
                        <Route path="/contact" component={Contact}/>
                    </Switch>
                </div>
            );
        }
    

    您的客户端构建配置构建/捆绑前端所需的一切。 JS, CSS, Images, ... 并将其放到 dist 文件夹中。

    您的服务器仅从根 / 提供此 dist 文件夹。这是您的服务器唯一做的事情(例如,除了提供 api)

    【讨论】:

    • 好的,我明白了,你的意思是我必须在client 中使用ExtractTextPlugin 来省略&lt;style&gt; 标签,然后在我的@ 中添加link props of helmet 987654339@ 在&lt;head&gt; 标签中添加&lt;link&gt; 标签。正是我的愿望被点燃了。谢谢。
    • 是的。您还可以另外使用 html-webpack-plugin。然后,将自动创建一个带有正确链接到您的 styles.css 和您的 javascript 文件的 html 文件!
    • 谢谢,在这种情况下我想不需要使用html-webpack-plugin,但是对于其他项目来说它是一个很好的指导,非常感谢。
    猜你喜欢
    • 2017-01-19
    • 2012-02-11
    • 2022-09-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多