60 실제 적용 후기
source: categories/study/vue-experiance/vue-experiance_9-60.md
60 실제 적용 후기
- eslint 기능 강화 - prettier, stylelint
- .babelrc: es6 module 문법 CommonJS 문법 변환 방지
- .eslintrc: lodash 라이브러리 사용 제한
- package.json sideEffects 설정
- vuetify tree shaking 적용
0. git hook 자동 설정 안될시 (git hook executable)
chmod ug+x .husky/*
chmod ug+x .git/hooks/*
0-1. eslint, prettier, stylelint 기능 추가함으로써 기대할 수 있는 효과
- 코드 스타일 공통화
- 리팩토링으로 인한 코드 최적화
- vue 관련 준수해야될 사항들 준수하게끔 강제할 수 있음
1. 초기 빌드 용량
2. .babelrc 설정
{
"presets": [
[
"@babel/preset-env",
{
"modules": false,
"debug": false
}
]
]
}
3. package.json 설정
{
"name": "",
"version": "0.1.0",
"sideEffects": false,
}
4. .eslintrc.js 설정
module.exports = {
root: true,
env: {
node: true,
},
extends: [
'eslint:recommended',
'plugin:prettier/recommended',
'prettier',
'plugin:vue/essential',
'plugin:vue/recommended',
'plugin:vue/strongly-recommended',
'plugin:storybook/recommended',
'@vue/prettier',
],
parserOptions: {
parser: 'babel-eslint',
},
rules: {
// 'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'off',
// 'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off',
'no-unused-vars': [
'error',
{ vars: 'all', args: 'after-used', ignoreRestSiblings: false },
],
'no-restricted-imports': [
'error',
{
name: 'lodash',
message:
'lodash has been prohibited due to bundle size. use lodash-es instead.',
},
],
// 'vue/no-unused-components': 'error',
// 'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'off',
// 'no-unused-vars': process.env.NODE_ENV === 'production' ? 'error' : 'off',
// 'vue/no-unused-components': process.env.NODE_ENV === 'production' ? 'error' : 'off',
// 'no-useless-escape': process.env.NODE_ENV === 'production' ? 'error' : 'off' // 'no-mixed-spaces-and-tabs': process.env.NODE_ENV === 'production' ? 'error' : 'off',
'prettier/prettier': [
'error',
{
singleQuote: true,
semi: true,
useTabs: true,
tabWidth: 2,
trailingComma: 'all',
printWidth: 80,
bracketSpacing: true,
arrowParens: 'avoid',
},
],
},
globals: {
kakao: false,
},
};
5. src/plugins/vuetify.js, vue.config.js
import Vue from 'vue';
import Vuetify from 'vuetify/lib';
Vue.use(Vuetify);
export default new Vuetify({
theme: {
disable: true,
},
});
const fs = require('fs');
const path = require('path');
const SpritesmithPlugin = require('webpack-spritesmith');
const ansiRegex = require('ansi-regex');
const autoprefixer = require('autoprefixer');
const filterRules = require('postcss-filter-rules');
const BundleAnalyzerPlugin =
require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
const VuetifyLoaderPlugin = require('vuetify-loader/lib/plugin');
module.exports = {
pluginOptions: {
i18n: {
locale: 'en',
fallbackLocale: 'en',
localeDir: 'locales',
enableInSFC: false,
},
},
// configureWebpack: {
// entry: ["@babel/polyfill", "./src/main.js"]
// },
configureWebpack: {
plugins: [
new VuetifyLoaderPlugin(),
new BundleAnalyzerPlugin({
openAnalyzer: false,
}),
// png 스프라이트 플러그인
...fs
.readdirSync(
path.join(__dirname, 'src/assets/images/sprites/spritesPng'),
)
.map(value =>
path.join(__dirname, `src/assets/images/sprites/spritesPng/${value}`),
)
.filter(value => !fs.statSync(value).isFile())
.map(value => {
const basename = path.basename(value);
return new SpritesmithPlugin({
src: {
cwd: path.resolve(
__dirname,
`src/assets/images/sprites/spritesPng/${basename}`,
),
glob: '*.png',
},
apiOptions: {
cssImageRef: `https://t1.kakaocdn.net/smartfactory/images/pc/sprite-${basename}.png`,
spritesheet_info: {
name: basename,
},
},
target: {
image: path.resolve(
__dirname,
`src/assets/images/sprites/sprite-${basename}.png`,
),
css: [
[
path.resolve(
__dirname,
`src/assets/scss/vendor/_sprite-${basename}.scss`,
),
{
format: 'handlebars_based_template',
},
],
],
},
customTemplates: {
handlebars_based_template: path.resolve(
__dirname,
'src/assets/scss/vendor/spritesmith-mixins.handlebars',
),
},
});
}),
],
},
chainWebpack: async () => {
// https://vuetifyjs.com/en/styles/css-reset/#bootstrapping
// vuetify global.sass, reset.scss 제거 (위 docs 참고 - 아래와같이 webpack 번들 실행되기 전에 내용 초기화방법밖엔 없는듯)
const data = '';
await fs.promises.writeFile(
path.join(
__dirname,
'/node_modules/vuetify/src/styles/elements/_index.sass',
),
data,
);
await fs.promises.writeFile(
path.join(
__dirname,
'/node_modules/vuetify/src/styles/generic/_index.scss',
),
data,
);
},
css: {
sourceMap: true,
loaderOptions: {
postcss: {
plugins: [
filterRules({
filter: selector => {
// const re = new RegExp(/^(html|body|\*|ul|ol|select|small)(\W|$)/, 'i')
const exception = '.v-application';
const exception1 = '.v-application--wrap';
const exception2 = '.v-main';
const exception3 = '.v-main__wrap';
// return !re.test(selector) || !selector.includes(exception)
return (
!selector.includes(exception) &&
!selector.includes(exception1) &&
!selector.includes(exception2) &&
!selector.includes(exception3)
);
},
keepAtRules: true,
}),
autoprefixer,
],
},
},
},
productionSourceMap: false,
transpileDependencies: [ansiRegex, 'vuetify'],
devServer: {
https: true,
proxy: {
// proxy할 경로
'/v1/': {
// proxy되는 target
target: process.env.PROXY_API,
// cross origin 허용
changeOrigin: true,
// 중간에 바꾸고 싶은 문자가 있는경우.
// 요청 /api/user/256 은 https://reqres.in/user/256 으로 변환
// pathRewrite: {'^/api' : ''},
},
'/delivery/': {
// proxy되는 target
target: process.env.PROXY_API,
// cross origin 허용
changeOrigin: true,
// 중간에 바꾸고 싶은 문자가 있는경우.
// 요청 /api/user/256 은 https://reqres.in/user/256 으로 변환
// pathRewrite: {'^/api' : ''},
},
'/common/': {
// proxy되는 target
target: process.env.PROXY_API,
// cross origin 허용
changeOrigin: true,
// 중간에 바꾸고 싶은 문자가 있는경우.
// 요청 /api/user/256 은 https://reqres.in/user/256 으로 변환
// pathRewrite: {'^/api' : ''},
},
'/transit/': {
// proxy되는 target
target: process.env.PROXY_API,
// cross origin 허용
changeOrigin: true,
// 중간에 바꾸고 싶은 문자가 있는경우.
// 요청 /api/user/256 은 https://reqres.in/user/256 으로 변환
// pathRewrite: {'^/api' : ''},
},
// "/transit/:id": {
// // proxy되는 target
// target: `${process.env.PROXY_API}/id`,
// // cross origin 허용
// changeOrigin: true
//
// // 중간에 바꾸고 싶은 문자가 있는경우.
// // 요청 /api/user/256 은 https://reqres.in/user/256 으로 변환
// // pathRewrite: {'^/api' : ''},
// }
},
disableHostCheck: true,
// historyApiFallback: true
},
};
6. 결과
31% 용량 감축