CSS 模块将 CSSes 导出为 head 标签中的 <style> 标签,并禁用 sourceMap
CSS Modules export CSSes as <style> tag in head tag with disabled sourceMap
我正在写一个 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
,因此所有样式都作为 <head>
标签内的 <style>
标签加载。
如果我将 soureMap
设置为 true
,<link>
标签出现在 <head>
标签内,即使它不是服务器端,并且有一个奇怪的斑点 url 加载 CSS
:
事实上,我想在服务器端 link 标签内直接指向 styles.css
,我该怎么做?
我的整个项目都在THIS LINK
代码不多,小而简单,就是一个简单的样板。 看看
对于生产构建,在 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"}]}
并向您的 App.jsx
添加一个 link
属性以在您的 <head>
标签中加载一个 <link>
标签。
所以你的 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>
);
}
您的客户端构建配置 builds/bundles 前端所需的一切。 JS,CSS,图像,...并将其放入 dist 文件夹。
您的服务器仅从根目录 / 提供此 dist 文件夹。这是你的服务器唯一做的事情(除了提供 api 例如)
我正在写一个 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
,因此所有样式都作为 <head>
标签内的 <style>
标签加载。
如果我将 soureMap
设置为 true
,<link>
标签出现在 <head>
标签内,即使它不是服务器端,并且有一个奇怪的斑点 url 加载 CSS
:
事实上,我想在服务器端 link 标签内直接指向 styles.css
,我该怎么做?
我的整个项目都在THIS LINK
代码不多,小而简单,就是一个简单的样板。 看看
对于生产构建,在 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"}]}
并向您的 App.jsx
添加一个 link
属性以在您的 <head>
标签中加载一个 <link>
标签。
所以你的 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>
);
}
您的客户端构建配置 builds/bundles 前端所需的一切。 JS,CSS,图像,...并将其放入 dist 文件夹。
您的服务器仅从根目录 / 提供此 dist 文件夹。这是你的服务器唯一做的事情(除了提供 api 例如)