`CSS` 输出文件中的奇怪`:local`
Weird `:local` in `CSS` output file
我简单声明一个key-frames
:
@keyframes spinner {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
但是在 CSS
文件中 Webpack
为我制作的文件中我看到:
animation: 1s infinite alternate :local(spinner)
什么是:local
???
我搜索并找到了一些解决方案,但为什么它出现在 css 中?
一些解决方案是,在我使用声明的动画的地方我必须使用 :global
:
:global .i-spinner4 {
animation: 1s infinite alternate spinner;
}
我使用了我找到的解决方案,它变得正确,但在 webpack -p
css 版本中它完全消失了,这意味着 PostCSS
prod 版本中的解析器完全忽略它...
我该如何解决这个问题???
这是我的开发版本webpack
配置:
const path = require('path');
const ExtractTextPlugin = require("extract-text-webpack-plugin"),
CleanWebpackPlugin = require('clean-webpack-plugin');
const DistDir = path.resolve(__dirname, './dist'),
SrcDir = path.resolve(__dirname, './src');
module.exports = {
resolve: {
alias: {
AppRoot: path.resolve(__dirname, './src/app'),
PcssRoot: path.resolve(__dirname, './src/pcss')
}
},
module: {
rules: [
{
test: /\.js$/,
exclude: ['src/app/redux', 'node_modules'],
include: SrcDir,
loader: 'babel-loader'
},
{
test: /\.pcss$/,
exclude: /node_modules/,
include: SrcDir,
use: ExtractTextPlugin.extract({
fallback: 'style-loader',
use: [
{
loader: 'css-loader',
options: {
importLoaders: 1,
modules: true,
localIdentName: '[local]',
sourceMap: true
}
},
{
loader: 'postcss-loader',
options: {
ident: 'postcss',
sourceMap: true,
syntax: 'postcss-scss',
map: true,
plugins: () => ([
require('postcss-partial-import')({
prefix: "_",
extension: ".pcss",
glob: false,
path: ['./src/pcss']
}),
require('postcss-nested-ancestors'),
require('postcss-apply'),
require('postcss-custom-properties'),
require('postcss-nested'),
require('postcss-cssnext')({
features: {
nesting: false
},
warnForDuplicates: false
}),
require('postcss-extend'),
require('css-mqpacker')({
sort: true
}),
require('autoprefixer')({
browsers: [`last 15 versions`]
})
])
}
}
]
})
},
{
test: /\.(woff|woff2|eot|ttf|svg)$/,
exclude: /node_modules/,
loader: 'file-loader',
options: {
limit: 1024,
name: '[name].[ext]',
publicPath: '../font/',
outputPath: 'asset/font/'
}
}
]
},
plugins: [
new ExtractTextPlugin({
filename: `asset/css/style.css`
}),
new CleanWebpackPlugin(`${DistDir}/asset`)
],
entry: {
"sd": `${SrcDir}/app/index.js`
},
externals: {
config: JSON.stringify(require(SrcDir + '/config/config.dev.json'))
},
output: {
path: DistDir,
filename: "asset/js/[name].bundle.js"
},
devServer: {inline: true},
devtool: 'source-map'
};
这是我的产品版本 webpack
:
const path = require('path');
const ExtractTextPlugin = require("extract-text-webpack-plugin"),
CleanWebpackPlugin = require('clean-webpack-plugin');
const DistDir = path.resolve(__dirname, './dist'),
SrcDir = path.resolve(__dirname, './src');
let q = [],
cache = {};
function randomNaming(length,limit) {
let result = '',
chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_',
fchars = 'abcdefghjklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_';
do {
if (q.length >= (52 * Math.pow(64, limit - 1)) && limit >= length) {
return 'OutOfPossibility';
} else if (q.length >= (52 * Math.pow(64, limit - 1)) && limit < length) {
++limit;
}
result = '';
result += fchars[Math.floor(Math.random() * fchars.length)];
for (let i = limit - 1; i > 0; --i) {
result += chars[Math.floor(Math.random() * chars.length)];
}
} while (q.includes(result));
q.push(result);
return result;
}
module.exports = {
resolve: {
alias: {
AppRoot: path.resolve(__dirname, './src/app'),
PcssRoot: path.resolve(__dirname, './src/pcss')
}
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
include: SrcDir,
loader: 'babel-loader'
},
{
test: /\.pcss$/,
exclude: /node_modules/,
include: SrcDir,
use: ExtractTextPlugin.extract({
fallback: 'style-loader',
use: [
{
loader: 'css-loader',
options: {
importLoaders: 1,
modules: true,
getLocalIdent: (loaderContext, localIdentName, localName, options) => {
var randName = randomNaming(3,2);
if (localName.match(/^i-/i)) {
randName = `i-${randName}`;
} else if (localName.match(/^i_/i)) {
randName = `i_`;
} else {
randName = `${randName}`;
}
if (typeof cache[localName] == 'undefined') {
cache[localName] = randName;
return cache[localName];
} else {
return cache[localName];
}
}
}
},
{
loader: 'postcss-loader',
options: {
ident: 'postcss',
syntax: 'postcss-scss',
plugins: () => ([
require('postcss-partial-import')({
prefix: "_",
extension: ".pcss",
glob: false,
path: ['./src/pcss']
}),
require('postcss-nested-ancestors'),
require('postcss-apply'),
require('postcss-custom-properties'),
require('postcss-nested'),
require('postcss-cssnext')({
features: {
nesting: false
},
warnForDuplicates: false
}),
require('postcss-extend'),
require('css-mqpacker')({
sort: true
}),
require('autoprefixer')({
browsers: [`last 15 versions`]
})/*,
require('postcss-csso')({
comments: false
})*/
])
}
}
]
})
},
{
test: /\.(woff|woff2|eot|ttf|svg)$/,
exclude: /node_modules/,
loader: 'file-loader',
options: {
limit: 1024,
name: '[hash:base64:3].[ext]',
publicPath: '../font/',
outputPath: 'asset/font/'
}
}
]
},
plugins: [
new ExtractTextPlugin({
filename: `asset/css/style.css`
}),
new CleanWebpackPlugin(`${DistDir}/asset`)
],
entry: {
"sd": `${SrcDir}/app/index.js`
},
externals: {
config: JSON.stringify(require(SrcDir + '/config/config.prod.json'))
},
output: {
path: DistDir,
filename: "asset/js/[name].bundle.js"
},
devServer: {inline: true},
};
这个问题是在我为 CSS Modules
声明 keyframes
而没有任何提示 css-loader
时产生的,我必须像下面这样写:
@keyframes :local(spinner) {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
当 Modules
在 css-loader
中是 true
时,每个 keyframes
必须用 :local
声明,然后用任何 class
轻松编写 class
=26=] 及其 animation
属性。如下所示:
.my-class {
animation: spinner 1s infinite alternate;
}
我最近在使用 css-loader
的 2.0.0 版本时遇到了这个问题。
这似乎是由它们的依赖项之一引起的错误,如本期相关:https://github.com/webpack-contrib/css-loader/issues/872
这个问题在 2.0.2 版本中已经修复,所以我升级到 2.0.2 就解决了。
先用动画的名字...
我能够通过简单地首先使用动画名称来摆脱失败的构建,如下所示
animation: spinner 1s infinite alternate
而不是 => 动画:1 秒旋转器无限交替
另一种解决方法是不使用动画 shorthand 属性。它会导致动画名称 localised,例如:
.fadein {
animation-duration: 300ms
animation-name: fadein
animation-fill-mode: forwards
}
@keyframes fadein {
from {
opacity: 0
}
}
我简单声明一个key-frames
:
@keyframes spinner {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
但是在 CSS
文件中 Webpack
为我制作的文件中我看到:
animation: 1s infinite alternate :local(spinner)
什么是:local
???
我搜索并找到了一些解决方案,但为什么它出现在 css 中?
一些解决方案是,在我使用声明的动画的地方我必须使用 :global
:
:global .i-spinner4 {
animation: 1s infinite alternate spinner;
}
我使用了我找到的解决方案,它变得正确,但在 webpack -p
css 版本中它完全消失了,这意味着 PostCSS
prod 版本中的解析器完全忽略它...
我该如何解决这个问题???
这是我的开发版本webpack
配置:
const path = require('path');
const ExtractTextPlugin = require("extract-text-webpack-plugin"),
CleanWebpackPlugin = require('clean-webpack-plugin');
const DistDir = path.resolve(__dirname, './dist'),
SrcDir = path.resolve(__dirname, './src');
module.exports = {
resolve: {
alias: {
AppRoot: path.resolve(__dirname, './src/app'),
PcssRoot: path.resolve(__dirname, './src/pcss')
}
},
module: {
rules: [
{
test: /\.js$/,
exclude: ['src/app/redux', 'node_modules'],
include: SrcDir,
loader: 'babel-loader'
},
{
test: /\.pcss$/,
exclude: /node_modules/,
include: SrcDir,
use: ExtractTextPlugin.extract({
fallback: 'style-loader',
use: [
{
loader: 'css-loader',
options: {
importLoaders: 1,
modules: true,
localIdentName: '[local]',
sourceMap: true
}
},
{
loader: 'postcss-loader',
options: {
ident: 'postcss',
sourceMap: true,
syntax: 'postcss-scss',
map: true,
plugins: () => ([
require('postcss-partial-import')({
prefix: "_",
extension: ".pcss",
glob: false,
path: ['./src/pcss']
}),
require('postcss-nested-ancestors'),
require('postcss-apply'),
require('postcss-custom-properties'),
require('postcss-nested'),
require('postcss-cssnext')({
features: {
nesting: false
},
warnForDuplicates: false
}),
require('postcss-extend'),
require('css-mqpacker')({
sort: true
}),
require('autoprefixer')({
browsers: [`last 15 versions`]
})
])
}
}
]
})
},
{
test: /\.(woff|woff2|eot|ttf|svg)$/,
exclude: /node_modules/,
loader: 'file-loader',
options: {
limit: 1024,
name: '[name].[ext]',
publicPath: '../font/',
outputPath: 'asset/font/'
}
}
]
},
plugins: [
new ExtractTextPlugin({
filename: `asset/css/style.css`
}),
new CleanWebpackPlugin(`${DistDir}/asset`)
],
entry: {
"sd": `${SrcDir}/app/index.js`
},
externals: {
config: JSON.stringify(require(SrcDir + '/config/config.dev.json'))
},
output: {
path: DistDir,
filename: "asset/js/[name].bundle.js"
},
devServer: {inline: true},
devtool: 'source-map'
};
这是我的产品版本 webpack
:
const path = require('path');
const ExtractTextPlugin = require("extract-text-webpack-plugin"),
CleanWebpackPlugin = require('clean-webpack-plugin');
const DistDir = path.resolve(__dirname, './dist'),
SrcDir = path.resolve(__dirname, './src');
let q = [],
cache = {};
function randomNaming(length,limit) {
let result = '',
chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_',
fchars = 'abcdefghjklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_';
do {
if (q.length >= (52 * Math.pow(64, limit - 1)) && limit >= length) {
return 'OutOfPossibility';
} else if (q.length >= (52 * Math.pow(64, limit - 1)) && limit < length) {
++limit;
}
result = '';
result += fchars[Math.floor(Math.random() * fchars.length)];
for (let i = limit - 1; i > 0; --i) {
result += chars[Math.floor(Math.random() * chars.length)];
}
} while (q.includes(result));
q.push(result);
return result;
}
module.exports = {
resolve: {
alias: {
AppRoot: path.resolve(__dirname, './src/app'),
PcssRoot: path.resolve(__dirname, './src/pcss')
}
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
include: SrcDir,
loader: 'babel-loader'
},
{
test: /\.pcss$/,
exclude: /node_modules/,
include: SrcDir,
use: ExtractTextPlugin.extract({
fallback: 'style-loader',
use: [
{
loader: 'css-loader',
options: {
importLoaders: 1,
modules: true,
getLocalIdent: (loaderContext, localIdentName, localName, options) => {
var randName = randomNaming(3,2);
if (localName.match(/^i-/i)) {
randName = `i-${randName}`;
} else if (localName.match(/^i_/i)) {
randName = `i_`;
} else {
randName = `${randName}`;
}
if (typeof cache[localName] == 'undefined') {
cache[localName] = randName;
return cache[localName];
} else {
return cache[localName];
}
}
}
},
{
loader: 'postcss-loader',
options: {
ident: 'postcss',
syntax: 'postcss-scss',
plugins: () => ([
require('postcss-partial-import')({
prefix: "_",
extension: ".pcss",
glob: false,
path: ['./src/pcss']
}),
require('postcss-nested-ancestors'),
require('postcss-apply'),
require('postcss-custom-properties'),
require('postcss-nested'),
require('postcss-cssnext')({
features: {
nesting: false
},
warnForDuplicates: false
}),
require('postcss-extend'),
require('css-mqpacker')({
sort: true
}),
require('autoprefixer')({
browsers: [`last 15 versions`]
})/*,
require('postcss-csso')({
comments: false
})*/
])
}
}
]
})
},
{
test: /\.(woff|woff2|eot|ttf|svg)$/,
exclude: /node_modules/,
loader: 'file-loader',
options: {
limit: 1024,
name: '[hash:base64:3].[ext]',
publicPath: '../font/',
outputPath: 'asset/font/'
}
}
]
},
plugins: [
new ExtractTextPlugin({
filename: `asset/css/style.css`
}),
new CleanWebpackPlugin(`${DistDir}/asset`)
],
entry: {
"sd": `${SrcDir}/app/index.js`
},
externals: {
config: JSON.stringify(require(SrcDir + '/config/config.prod.json'))
},
output: {
path: DistDir,
filename: "asset/js/[name].bundle.js"
},
devServer: {inline: true},
};
这个问题是在我为 CSS Modules
声明 keyframes
而没有任何提示 css-loader
时产生的,我必须像下面这样写:
@keyframes :local(spinner) {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
当 Modules
在 css-loader
中是 true
时,每个 keyframes
必须用 :local
声明,然后用任何 class
轻松编写 class
=26=] 及其 animation
属性。如下所示:
.my-class {
animation: spinner 1s infinite alternate;
}
我最近在使用 css-loader
的 2.0.0 版本时遇到了这个问题。
这似乎是由它们的依赖项之一引起的错误,如本期相关:https://github.com/webpack-contrib/css-loader/issues/872
这个问题在 2.0.2 版本中已经修复,所以我升级到 2.0.2 就解决了。
先用动画的名字...
我能够通过简单地首先使用动画名称来摆脱失败的构建,如下所示
animation: spinner 1s infinite alternate
而不是 => 动画:1 秒旋转器无限交替
另一种解决方法是不使用动画 shorthand 属性。它会导致动画名称 localised,例如:
.fadein {
animation-duration: 300ms
animation-name: fadein
animation-fill-mode: forwards
}
@keyframes fadein {
from {
opacity: 0
}
}