개발에서는 작동하지만 Prod에서는 작동하지 않는 Vue JS에서 요소를 제거할 때의 애니메이션
CSS 트랜지션을 사용하면 값이 변경될 때마다 애니메이션이 표시되는 컴포넌트가 있습니다.
이 작업을 수행할 때npm run dev이 모든 것은 다음과 같이 정상적으로 동작합니다.
단, 사용시npm run buildNginx 서버에서 코드를 실전 가동 상태로 만들면 애니메이션이 작동하지 않고 요소가 매우 빠르게 제거됩니다.
dev와 prod의 차이점이 애니메이션 효과를 얻을 수 있는 더 좋은 방법은 없을까?
이 버그를 재현하기 위해 사용하고 있는 BugRepro.vue:
<template>
<div class="bugrepro">
<div class="empty-space"></div>
<Value :value="someNumber"></Value>
<button @click="change()">Change it!</button>
</div>
</template>
<script>
import Value from "./Value"
export default {
name: "BugRepro",
data() {
return {
someNumber: 20
};
},
components :{
Value
},
methods: {
change() {
this.someNumber += 1;
}
}
};
</script>
<style>
.empty-space {
margin-top: 100px;
}
</style>
Value.vue. 이 번호는 값을 유지하고 있으며 값이 변경되었을 때 애니메이션 처리를 담당합니다.
<template>
<div class="card-property">
<button class="btn btn-sm active fa" :class="`btn-info fa-tint`" style="cursor:default" title="Mana Cost">
{{ value }}
</button>
<transition-group name="diff-once" class="pos-absolute" tag="div" @after-enter="removeDiff()">
<button v-for="diff in diffs" :key="diff.id"
class="btn btn-sm active fa diff-once" :class="`btn-info fa-tint`" style="cursor:default">
{{diff.value}}
</button>
</transition-group>
</div>
</template>
<script>
export default {
name: "Value",
props: ["value"],
data() {
return {
diffs: [],
diffId: 0
};
},
methods: {
removeDiff() {
this.diffs.splice(0, 1);
}
},
watch: {
value: function(newValue, oldValue) {
console.log(typeof newValue);
let diff = newValue - oldValue;
this.diffs.push({value: diff, id: this.diffId});
this.diffId++;
}
}
}
</script>
<style>
.card-property {
position: relative;
}
.diff-once-leave-active {
transition: all 1s;
position: absolute;
}
.pos-absolute {
position: absolute;
top: 0;
left: 0;
}
.diff-once-leave {
opacity: 1;
}
.diff-once-leave-to {
opacity: 0;
transform: translateY(-30px);
}
</style>
webpack.prod.conf에 문제가 있을 수 있다는 것을 고려했습니다.이미 webpack.prod.conf를 디세블로 해 보았습니다.OptimizeCSSPlugin도움이 되지 않았습니다.
'use strict'
const path = require('path')
const utils = require('./utils')
const webpack = require('webpack')
const config = require('../config')
const merge = require('webpack-merge')
const baseWebpackConfig = require('./webpack.base.conf')
const CopyWebpackPlugin = require('copy-webpack-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const ExtractTextPlugin = require('extract-text-webpack-plugin')
const OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin')
const UglifyJsPlugin = require('uglifyjs-webpack-plugin')
const env = process.env.NODE_ENV === 'testing'
? require('../config/test.env')
: require('../config/prod.env')
const webpackConfig = merge(baseWebpackConfig, {
module: {
rules: utils.styleLoaders({
sourceMap: config.build.productionSourceMap,
extract: true,
usePostCSS: true
})
},
devtool: config.build.productionSourceMap ? config.build.devtool : false,
output: {
path: config.build.assetsRoot,
filename: utils.assetsPath('js/[name].[chunkhash].js'),
chunkFilename: utils.assetsPath('js/[id].[chunkhash].js')
},
plugins: [
// http://vuejs.github.io/vue-loader/en/workflow/production.html
new webpack.DefinePlugin({
'process.env': env
}),
new UglifyJsPlugin({
uglifyOptions: {
compress: {
warnings: false
}
},
sourceMap: config.build.productionSourceMap,
parallel: true
}),
// extract css into its own file
new ExtractTextPlugin({
filename: utils.assetsPath('css/[name].[contenthash].css'),
// Setting the following option to `false` will not extract CSS from codesplit chunks.
// Their CSS will instead be inserted dynamically with style-loader when the codesplit chunk has been loaded by webpack.
// It's currently set to `true` because we are seeing that sourcemaps are included in the codesplit bundle as well when it's `false`,
// increasing file size: https://github.com/vuejs-templates/webpack/issues/1110
allChunks: true,
}),
// Compress extracted CSS. We are using this plugin so that possible
// duplicated CSS from different components can be deduped.
new OptimizeCSSPlugin({
cssProcessorOptions: config.build.productionSourceMap
? { safe: true, map: { inline: false } }
: { safe: true }
}),
// generate dist index.html with correct asset hash for caching.
// you can customize output by editing /index.html
// see https://github.com/ampedandwired/html-webpack-plugin
new HtmlWebpackPlugin({
filename: process.env.NODE_ENV === 'testing'
? 'index.html'
: config.build.index,
template: 'index.html',
inject: true,
minify: {
removeComments: true,
collapseWhitespace: true,
removeAttributeQuotes: true
// more options:
// https://github.com/kangax/html-minifier#options-quick-reference
},
// necessary to consistently work with multiple chunks via CommonsChunkPlugin
chunksSortMode: 'dependency'
}),
// keep module.id stable when vendor modules does not change
new webpack.HashedModuleIdsPlugin(),
// enable scope hoisting
new webpack.optimize.ModuleConcatenationPlugin(),
// split vendor js into its own file
new webpack.optimize.CommonsChunkPlugin({
name: 'vendor',
minChunks (module) {
// any required modules inside node_modules are extracted to vendor
return (
module.resource &&
/\.js$/.test(module.resource) &&
module.resource.indexOf(
path.join(__dirname, '../node_modules')
) === 0
)
}
}),
// extract webpack runtime and module manifest to its own file in order to
// prevent vendor hash from being updated whenever app bundle is updated
new webpack.optimize.CommonsChunkPlugin({
name: 'manifest',
minChunks: Infinity
}),
// This instance extracts shared chunks from code splitted chunks and bundles them
// in a separate chunk, similar to the vendor chunk
// see: https://webpack.js.org/plugins/commons-chunk-plugin/#extra-async-commons-chunk
new webpack.optimize.CommonsChunkPlugin({
name: 'app',
async: 'vendor-async',
children: true,
minChunks: 3
}),
// copy custom static assets
new CopyWebpackPlugin([
{
from: path.resolve(__dirname, '../static'),
to: config.build.assetsSubDirectory,
ignore: ['.*']
}
])
]
})
if (config.build.productionGzip) {
const CompressionWebpackPlugin = require('compression-webpack-plugin')
webpackConfig.plugins.push(
new CompressionWebpackPlugin({
asset: '[path].gz[query]',
algorithm: 'gzip',
test: new RegExp(
'\\.(' +
config.build.productionGzipExtensions.join('|') +
')$'
),
threshold: 10240,
minRatio: 0.8
})
)
}
if (config.build.bundleAnalyzerReport) {
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
webpackConfig.plugins.push(new BundleAnalyzerPlugin())
}
module.exports = webpackConfig
어떤 파일이 관련된지는 모르기 때문에 github에서도 모든 파일을 찾을 수 있습니다.
재현하기 쉬운 순서:
- 체크아웃 소스 코드, 실행
npm install그리고.npm run dev - http://localhost:42637로 이동하여 버튼을 클릭합니다.애니메이션이 올바르게 동작하고 있습니다.
- 개발 서버를 중지하고 실행
npm run build - Nginx와 같은 일부 HTTP 서버에서 파일 호스트
- 파일을 호스트하는 HTTP 서버로 이동하여 버튼을 클릭합니다.애니메이션이 작동하지 않습니다.
어떤 파일이 가장 적절한지 알게 되면 당연히 이 게시물에 추가합니다.
문제는 운영 환경에 컴파일하면 부트스트랩과 컴포넌트의 모든 CSS 파일이 하나로 결합되어 일부 CSS 최적화를 통해 실행된다는 것입니다.이것에 의해, CSS 스타일은 복수의 포인트로 천이를 정의합니다.여기 네 것이 있습니다..diff-once-...스타일도 있고.btn스타일DEV 모드에서는.diff-once-...더 높은 캐스케이드, 생산량, 더 높은 캐스케이드, 생산량에서 더 높습니다..btn따라서 버튼의 이행규칙은 나중에 정의한 모든 규칙을 덮어씁니다.애니메이션 수업에서 특정성을 높여서 이 문제를 해결할 수 있습니다.
.btn.diff-once-leave-to { ... }
.btn.diff-once-leave { ... }
또는 범위 스타일을 추가하여(권장).이렇게 하면 모든 애니메이션 스타일은 기본적으로 더 높은 특수성을 가지며 앱의 다른 스타일에 영향을 주지 않습니다.
<style scoped>
.card-property {
position: relative;
}
.diff-once-leave-active {
transition: all 1s;
position: absolute;
}
.pos-absolute {
position: absolute;
top: 0;
left: 0;
}
.diff-once-leave {
opacity: 1;
}
.diff-once-leave-to {
opacity: 0;
transform: translateY(-30px);
}
</style>
이게 도움이 됐으면 좋겠네요!
언급URL : https://stackoverflow.com/questions/50824857/animation-when-removing-element-in-vue-js-working-in-dev-but-not-in-prod
'programing' 카테고리의 다른 글
| Vuex 스토어에서 알 수 없는 로컬 작업 유형을 가져오는 중 (0) | 2022.08.07 |
|---|---|
| 첫 번째 로드에서만 mapGetters의 반응성 문제 (0) | 2022.08.07 |
| v-if 조건이 계산된 속성에서 업데이트되지 않음 (0) | 2022.08.07 |
| 키 누르기 vuejs에서는 소수점 2자리 제한이 있는 숫자와 점 하나만 허용 (0) | 2022.08.07 |
| 메모리셋을 사용하는 것보다 메모리를 제로화하는 속도가 더 빠릅니까? (0) | 2022.08.07 |

