Модули CSS экспортируют CSS как тег <style>в теге head с отключенной исходной картой - PullRequest
0 голосов
/ 24 апреля 2018

Я пишу шаблон React, Server Side Rendering, Router4, Helmet, CSS 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, поэтому все стили загружаются как тег <style> внутри тега <head>.

Shitty Loading CSS as style tag inside head tag because of setting sourceMaps to false

Если я установлю soureMap на true, тег <link> появится внутри тега <head>, даже если он не на стороне сервера и имеет странный URL-адрес для загрузки CSS:

Results after setting sourceMaps to true

На самом деле я хочу использовать тег ссылки на стороне сервера внутри тега head с прямым указанием на styles.css, как мне это сделать?

Весь мой проект в THIS LINK

У него не очень много кодов, мало и просто, это просто шаблон. посмотрите

1 Ответ

0 голосов
/ 24 апреля 2018

Для производственных сборок, внутри client config, вы не используете загрузчик стилей.Вам нужно использовать extract-text-webpack-plugin вместо этого.Вы сделали это правильно в вашем server build config.Но эта конфигурация не должна быть в вашей серверной сборке, так как в исходном коде сервера вы никогда не используете файлы 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, чтобы загрузить тег <link> внутри тега <head>.

Таким образом, ваш метод визуализации 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 только от root /.Это единственное, что делает ваш сервер (помимо предоставления API, например)

...