vue-cli 비계 의 웹 팩 설정 방법 을 자세히 설명 합 니 다.
웹 팩 은 module bundler(모듈 패키지 도구)입 니 다.모듈 이란 일반적인 전단 개발 에서 자바 스 크 립 트,CSS,이미지 등 정적 자원 을 사용 하 는 것 입 니 다.웹 팩 은 이러한 정적 자원 파일 을 모듈 이 라 고 부 릅 니 다.
웹 팩 은 AMD 와 CommonJS,그리고 다른 일부 모듈 시스템 을 지원 하고 다양한 JS 쓰기 규범 을 호 환 하여 모듈 간 의 관 계 를 처리 할 수 있 기 때문에 더욱 강력 한 JS 모듈 화 기능 을 가지 고 정적 자원 에 대해 통일 적 인 관리 와 포장 을 할 수 있 습 니 다.홈 페이지 에서 이 사진 으로 소개 합 니 다.
이 는 많은 곳 에서 Grunt 와 Gulp 를 대체 할 수 있 습 니 다.포장 CSS 를 컴 파일 하고 CSS 예비 처 리 를 하 며 JS 의 방언 을 컴 파일 하고 그림 을 포장 하 며 코드 압축 등 을 할 수 있 기 때 문 입 니 다.그래서 제 가 웹 팩 을 접 하고 나 서 gulp 를 별로 쓰 고 싶 지 않 았 어 요.
웹 팩 을 왜 사용 합 니까?
총 결 은 다음 과 같다.
웹 팩 은 주로 vue 와 React 에 많이 사용 되 는데 사실은 Browserify 와 매우 비슷 하지만 응용 프로그램 을 여러 파일 로 포장 합 니 다.한 페이지 에 여러 페이지 가 적용 된다 면 사용 자 는 해당 페이지 의 코드 만 다운로드 할 수 있 습 니 다.다른 페이지 에 접근 할 때 일반적인 코드 를 다시 다운로드 할 필요 가 없습니다.
본인 프로젝트 기반 사용
vue webpack 의 프로필 의 기본 디 렉 터 리 구 조 는 다음 과 같 습 니 다.
config
├── dev.env.js //dev
├── index.js // dev prod
└── prod.env.js // prod
build
├── build.js // npm run build
├── check-versions.js // npm node
├── logo.png
├── utils.js // , cssLoader styleLoader
├── vue-loader.conf.js // vueloader
├── webpack.base.conf.js // dev prod
├── webpack.dev.conf.js // dev
└── webpack.prod.conf.js // prod
Config 폴 더 아래 파일 설명dev.env.js
config 내 파일 은 build 에 서 비 스 를 제공 합 니 다.대부분 변 수 를 정의 합 니 다 export
use strict //[ ]
/**
* [webpack-merge ,
]
*/
const merge = require('webpack-merge')
const prodEnv = require('./prod.env')
module.exports = merge(prodEnv, {
NODE_ENV: '"development"'
})
prod.env.js개발 시 dev.env.js 의 개발 환경 설정 을 가 져 오고 발표 시 prod.env.js 의 생산 환경 설정 을 호출 합 니 다.
use strict
module.exports = {
NODE_ENV: '"production"'
}
index.js
const path = require('path')
module.exports = {
/**
* [ ]
*/
dev: {
assetsSubDirectory: 'static', // [ , css,js,image ]
assetsPublicPath: '/', // [ ]
/**
* [ ]
*/
proxyTable: {
'/hcm': {
target: 'https://127.0.0.1:8448',
changeOrigin: true,
secure: false
},
headers: {
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Methods": "GET, POST, PUT, DELETE, PATCH, OPTIONS",
"Access-Control-Allow-Headers": "X-Requested-With, content-type, Authorization"
}
},
host: '127.0.0.1', // [ ]
port: 8083, // [ , ]
autoOpenBrowser: true, // [ ( npm run dev) http://127.0.0.1:8083/ ]
errorOverlay: true, // [ ]
notifyOnErrors: true, // [ ]
poll:false, // [ (file system) devServer.watchOptions]
useEslint: true, // [ ]
showEslintErrorsInOverlay: false, // [ eslint ]
devtool: 'eval-source-map', // [ , ]
cacheBusting: true, // [ ]
cssSourceMap: false // [ bug , sourcemap , , ]
},
/**
* [ ]
*/
build: {
/**
* [index、login、license、forbidden、notfound、Internal.licenses , ]
*/
index: path.resolve(__dirname, '../../hcm-modules/hcm-web/src/main/resources/META-INF/resources/index.html'),
login: path.resolve(__dirname, '../../hcm-modules/hcm-web/src/main/resources/META-INF/resources/login.html'),
license: path.resolve(__dirname, '../../hcm-modules/hcm-web/src/main/resources/META-INF/resources/license.html'),
forbidden: path.resolve(__dirname, '../../hcm-modules/hcm-web/src/main/resources/META-INF/resources/error/403.html'),
notfound: path.resolve(__dirname, '../../hcm-modules/hcm-web/src/main/resources/META-INF/resources/error/404.html'),
internal: path.resolve(__dirname, '../../hcm-modules/hcm-web/src/main/resources/META-INF/resources/error/500.html'),
licenses: path.resolve(__dirname, '../../hcm-modules/hcm-web/src/main/resources/META-INF/resources/docs/licenses.html'),
/**
* [ ]
*/
assetsRoot: path.resolve(__dirname, '../../hcm-modules/hcm-web/src/main/resources/META-INF/resources'),
assetsSubDirectory: 'static', //js、css、images
assetsPublicPath: './', // , dist , ./。 ,
productionSourceMap: true,
devtool: '#source-map',
productionGzip: false, //unit gzip ,gzip js css
productionGzipExtensions: ['js', 'css'],
bundleAnalyzerReport: process.env.npm_config_report //
}
}
build 폴 더 아래 파일 설명build.js
이 파일 은 생산 버 전 을 구축 하 는 역할 을 합 니 다.package.json 의 scripts build 는 node build/build.js 입 니 다.명령 행 npm run build 를 입력 하여 이 파일 을 컴 파일 하여 생산 환경 을 만 드 는 코드 입 니 다.
require('./check-versions')() //check-versions: 。 ()
process.env.NODE_ENV = 'production' //
/**
*
*/
const ora = require('ora') //
const rm = require('rimraf') //
const path = require('path')
const chalk = require('chalk') //
const webpack = require('webpack')
const config = require('../config') // index.js
const webpackConfig = require('./webpack.prod.conf')
const spinner = ora('building for production...') // start ,
spinner.start()
// dist , hash ,
rm(path.join(config.build.assetsRoot, config.build.assetsSubDirectory), err => {
if (err) throw err
webpack(webpackConfig, (err, stats) => {
spinner.stop()
if (err) throw err
process.stdout.write(stats.toString({
colors: true,
modules: false,
children: false,
chunks: false,
chunkModules: false
}) + '
')
if (stats.hasErrors()) {
console.log(chalk.red(' Build failed with errors.
'))
process.exit(1)
}
console.log(chalk.cyan(' Build complete.
'))
console.log(chalk.yellow(
' Tip: built files are meant to be served over an HTTP server.
' +
' Opening index.html over file:// won\'t work.
'
))
})
})
check-versions.js이 파일 은 node 와 npm 버 전 을 검사 하 는 데 사용 되 며 버 전 의존 도 를 실현 합 니 다.
const chalk = require('chalk')
const semver = require('semver') //
const packageConfig = require('../package.json')
const shell = require('shelljs')
function exec (cmd) {
// child_process , Unix
return require('child_process').execSync(cmd).toString().trim()
}
const versionRequirements = [
{
name: 'node',
currentVersion: semver.clean(process.version), // semver
versionRequirement: packageConfig.engines.node // package.json node
}
]
if (shell.which('npm')) {
versionRequirements.push({
name: 'npm',
currentVersion: exec('npm --version'), // npm --version , exec ,
versionRequirement: packageConfig.engines.npm
})
}
module.exports = function () {
const warnings = []
for (let i = 0; i < versionRequirements.length; i++) {
const mod = versionRequirements[i]
if (!semver.satisfies(mod.currentVersion, mod.versionRequirement)) {
// package.json ,
warnings.push(mod.name + ': ' +
chalk.red(mod.currentVersion) + ' should be ' +
chalk.green(mod.versionRequirement)
)
}
}
if (warnings.length) {
console.log('')
console.log(chalk.yellow('To use this template, you must update following to modules:'))
console.log()
for (let i = 0; i < warnings.length; i++) {
const warning = warnings[i]
console.log(' ' + warning)
}
console.log()
process.exit(1)
}
}
utils.jsutils 는 도구 라 는 뜻 으로 css 를 처리 하 는 파일 입 니 다.
const path = require('path')
const config = require('../config')
const ExtractTextPlugin = require('extract-text-webpack-plugin')
const packageConfig = require('../package.json')
exports.assetsPath = function (_path) {
const assetsSubDirectory = process.env.NODE_ENV === 'production'
? config.build.assetsSubDirectory
: config.dev.assetsSubDirectory
return path.posix.join(assetsSubDirectory, _path)
}
exports.cssLoaders = function (options) {
options = options || {}
// css-loader postcssLoader, options.usePostCSS postcssLoader
const cssLoader = {
loader: 'css-loader',
options: {
sourceMap: options.sourceMap
}
}
const postcssLoader = {
loader: 'postcss-loader',
options: {
sourceMap: options.sourceMap
}
}
// generate loader string to be used with extract text plugin
function generateLoaders (loader, loaderOptions) {
const loaders = options.usePostCSS ? [cssLoader, postcssLoader] : [cssLoader]
if (loader) {
loaders.push({
loader: loader + '-loader',
//Object.assign es6 ,
options: Object.assign({}, loaderOptions, {
sourceMap: options.sourceMap
})
})
}
// Extract CSS when that option is specified
// (which is the case during production build)
if (options.extract) {
//ExtractTextPlugin , loaders, vue-style-loader
return ExtractTextPlugin.extract({
use: loaders,
fallback: 'vue-style-loader',
publicPath: '../../'
})
} else {
// vue-style-loader loaders
return ['vue-style-loader'].concat(loaders)
}
}
// https://vue-loader.vuejs.org/en/configurations/extract-css.html
return {
css: generateLoaders(),// css-loader vue-style-loader
postcss: generateLoaders(),// css-loader postcssLoader vue-style-loader
less: generateLoaders('less'), // less-loader vue-style-loader
sass: generateLoaders('sass', { indentedSyntax: true }), // sass-loader vue-style-loader
scss: generateLoaders('sass'), // sass-loader vue-style-loader
stylus: generateLoaders('stylus'), // stylus-loader vue-style-loader
styl: generateLoaders('stylus') // stylus-loader vue-style-loader
}
}
// Generate loaders for standalone style files (outside of .vue)
exports.styleLoaders = function (options) {
const output = []
const loaders = exports.cssLoaders(options)
// css,less,sass output
for (const extension in loaders) {
const loader = loaders[extension]
output.push({
test: new RegExp('\\.' + extension + '$'),
use: loader
})
}
return output
}
exports.createNotifierCallback = () => {
//
const notifier = require('node-notifier')
return (severity, errors) => {
if (severity !== 'error') return
// , ,
const error = errors[0]
const filename = error.file && error.file.split('!').pop()
notifier.notify({
title: packageConfig.name,
message: severity + ': ' + error.name,
subtitle: filename || '',
icon: path.join(__dirname, 'logo.png')
})
}
}
vue-loader.conf.js이 파일 의 주요 역할 은.vue 파일 을 처리 하고 이 파일 의 모든 언어 블록(template,script,style)을 분석 하여 js 가 사용 할 수 있 는 js 모듈 로 변환 하 는 것 입 니 다.
const utils = require('./utils')
const config = require('../config')
const isProduction = process.env.NODE_ENV === 'production'
const sourceMapEnabled = isProduction
? config.build.productionSourceMap
: config.dev.cssSourceMap
// css , sourceMap, extract
module.exports = {
loaders: utils.cssLoaders({
sourceMap: sourceMapEnabled,
extract: isProduction
}),
cssSourceMap: sourceMapEnabled,
cacheBusting: config.dev.cacheBusting,
// , , src , require , webpack
transformToRequire: {
video: ['src', 'poster'],
source: 'src',
img: 'src',
image: 'xlink:href'
}
}
webpack.base.conf.js웹 팩.base.conf.js 는 개발 과 생산 이 공동으로 사용 하 는 기본 설정 파일 로 주로 배합 입구,출력 환경 설정,모듈 resolve 와 플러그 인 설정 등 을 실현 합 니 다.
const path = require('path')
const utils = require('./utils')
/**
* [ index.js ]
*/
const config = require('../config')
const vueLoaderConfig = require('./vue-loader.conf')
/**
* [ ]
* @param dir [ ]
*_dirname *
*@return
*/
function resolve (dir) {
return path.join(__dirname, '..', dir)
}
const createLintingRule = () => ({
test: /\.(js|vue)$/,
loader: 'eslint-loader',
enforce: 'pre',
include: [resolve('src'), resolve('test')],
options: {
formatter: require('eslint-friendly-formatter'),
emitWarning: !config.dev.showEslintErrorsInOverlay
}
})
module.exports = {
context: path.resolve(__dirname, '../'),
/**
* [ ]
*/
entry: {
/**
* [ , babel-polyfill es6 ]
*/
app: ['babel-polyfill', './src/main.js'],
login: ['babel-polyfill', './src/loginMain.js'],
license: ['babel-polyfill', './src/licenseMain.js']
},
/**
* [ ]
*/
output: {
path: config.build.assetsRoot,
filename: '[name].js',
publicPath: process.env.NODE_ENV === 'production'
? config.build.assetsPublicPath
: config.dev.assetsPublicPath //
},
resolve: {
/**
* [extensions: , important , ]
*/
extensions: ['.js', '.vue', '.json'],
/**
* [alias ]
*/
alias: {
'vue$': 'vue/dist/vue.esm.js',
'@': resolve('src')
}
},
/**
*
*/
module: {
rules: [
...(config.dev.useEslint ? [createLintingRule()] : []),
/**
* [ vue-loader vue js ]
*/
{
test: /\.vue$/,
loader: 'vue-loader',
options: vueLoaderConfig
},
/**
* [ babel-loader js es5/es6 ]
*/
{
test: /\.js$/,
loader: 'babel-loader',
include: [resolve('src'), resolve('test')]
},
/**
* [ 、 、 url-loader , 10000 base64]
*/
{
test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: utils.assetsPath('img/[name].[hash:7].[ext]')
}
},
{
test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: utils.assetsPath('media/[name].[hash:7].[ext]')
}
},
{
test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: utils.assetsPath('fonts/[name].[hash:7].[ext]')
}
},
/**
* [canvas ]
*/
{
test: path.resolve(`${resolve('src')}/lib/jtopo.js`),
loader: ['exports-loader?window.JTopo', 'script-loader']
}
]
},
// Node.js , webpack Node.js vue
node: {
setImmediate: false,
dgram: 'empty',
fs: 'empty',
net: 'empty',
tls: 'empty',
child_process: 'empty'
}
}
webpack.dev.conf.js
const path = require('path')
const utils = require('./utils')
const webpack = require('webpack')
const config = require('../config')
// webpack-merge webpack.dev.conf.js wepack.base.config.js
const merge = require('webpack-merge')
const baseWebpackConfig = require('./webpack.base.conf')
const HtmlWebpackPlugin = require('html-webpack-plugin')
// webpack
const FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin')
// , 8000
const portfinder = require('portfinder')
// processs node , host
const HOST = process.env.HOST
const PORT = process.env.PORT && Number(process.env.PORT)
function resolveApp(relativePath) {
return path.resolve(relativePath);
}
const devWebpackConfig = merge(baseWebpackConfig, {
module: {
// utils styleLoaders, css,less,postcss
rules: utils.styleLoaders({ sourceMap: config.dev.cssSourceMap, usePostCSS: true })
},
//
devtool: config.dev.devtool,
// config index.js
devServer: {
// none, error, warning info
clientLogLevel: 'warning',
// HTML5 History API
historyApiFallback: true,
hot: true, //
compress: true, //
host: HOST || config.dev.host,
port: PORT || config.dev.port,
open: config.dev.autoOpenBrowser, //
overlay: config.dev.errorOverlay
? { warnings: false, errors: true }
: false,
publicPath: config.dev.assetsPublicPath,
proxy: config.dev.proxyTable,//
quiet: true, // , FriendlyErrorsPlugin true watchOptions: {
poll: config.dev.poll, //
}
},
plugins: [
new webpack.DefinePlugin({
'process.env': require('../config/dev.env')
}),
new webpack.HotModuleReplacementPlugin(),// ,
new webpack.NamedModulesPlugin(), //
new webpack.NoEmitOnErrorsPlugin(), // webpack , ,
// https://github.com/ampedandwired/html-webpack-plugin
// html5
new HtmlWebpackPlugin({
filename: 'index.html',
template: 'index.html',
inject: true,
chunks: ['app']
}),
new HtmlWebpackPlugin({
filename: 'login.html',
template: 'login.html',
inject: true,
chunks: ['login']
}),
new HtmlWebpackPlugin({
filename: 'license.html',
template: 'license.html',
inject: true,
chunks: ['license']
}),
new HtmlWebpackPlugin({
filename: 'licenses.html',
template: 'licenses.html',
inject: true,
chunks: []
}),
new HtmlWebpackPlugin({
filename: '404.html',
template: path.resolve(__dirname, '../errors/404.html'),
favicon: resolveApp('favicon.ico'),
inject: true,
chunks: []
}),
new HtmlWebpackPlugin({
filename: '403.html',
template: path.resolve(__dirname, '../errors/403.html'),
favicon: resolveApp('favicon.ico'),
inject: true,
chunks: []
}),
new HtmlWebpackPlugin({
filename: '500.html',
template: path.resolve(__dirname, '../errors/500.html'),
favicon: resolveApp('favicon.ico'),
inject: true,
chunks: []
})
]
})
module.exports = new Promise((resolve, reject) => {
portfinder.basePort = process.env.PORT || config.dev.port
//
portfinder.getPort((err, port) => {
if (err) {
reject(err)
} else {
// evn devServer
process.env.PORT = port
// add port to devServer config
devWebpackConfig.devServer.port = port
//
devWebpackConfig.plugins.push(new FriendlyErrorsPlugin({
compilationSuccessInfo: {
messages: [`Your application is running here: http://${devWebpackConfig.devServer.host}:${port}`],
},
onErrors: config.dev.notifyOnErrors
? utils.createNotifierCallback()
: undefined
}))
resolve(devWebpackConfig)
}
})
})
webpack.prod.conf.js
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 = require('../config/prod.env')
function resolveApp(relativePath) {
return path.resolve(relativePath);
}
const webpackConfig = merge(baseWebpackConfig, {
module: {
rules: utils.styleLoaders({
sourceMap: config.build.productionSourceMap,// 。 true
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 // :true ,false
}
},
sourceMap: config.build.productionSourceMap,
parallel: true
}),
// extract css into its own file
// 。 index style , ,
new ExtractTextPlugin({
filename: utils.assetsPath('css/[name].[contenthash].css'),
allChunks: true,
}),
// css
new OptimizeCSSPlugin({
cssProcessorOptions: config.build.productionSourceMap
? { safe: true, map: { inline: false } }
: { safe: true }
}),
//html
new HtmlWebpackPlugin({
filename: config.build.index,
template: 'index.html',
inject: true,
//
minify: {
removeComments: true, //
collapseWhitespace: true, //
removeAttributeQuotes: true //
},
chunks: ['vendor', 'manifest', 'app'],
// necessary to consistently work with multiple chunks via CommonsChunkPlugin
chunksSortMode: 'dependency'
}),
new HtmlWebpackPlugin({
filename: config.build.login,
template: 'login.html',
inject: true,
minify: {
removeComments: true,
collapseWhitespace: true,
removeAttributeQuotes: true
},
chunks: ['vendor', 'manifest', 'login'],
// necessary to consistently work with multiple chunks via CommonsChunkPlugin
chunksSortMode: 'dependency'
}),
new HtmlWebpackPlugin({
filename: config.build.license,
template: 'license.html',
inject: true,
minify: {
removeComments: true,
collapseWhitespace: true,
removeAttributeQuotes: true
},
chunks: ['vendor', 'manifest', 'license'],
// necessary to consistently work with multiple chunks via CommonsChunkPlugin
chunksSortMode: 'dependency'
}),
new HtmlWebpackPlugin({
filename: config.build.notfound,
template: path.resolve(__dirname, '../errors/404.html'),
inject: true,
favicon: resolveApp('favicon.ico'),
minify: {
removeComments: true,
collapseWhitespace: true,
removeAttributeQuotes: true
},
chunks: [],
// necessary to consistently work with multiple chunks via CommonsChunkPlugin
chunksSortMode: 'dependency'
}),
new HtmlWebpackPlugin({
filename: config.build.forbidden,
template: path.resolve(__dirname, '../errors/403.html'),
inject: true,
favicon: resolveApp('favicon.ico'),
minify: {
removeComments: true,
collapseWhitespace: true,
removeAttributeQuotes: true
},
chunks: [],
// necessary to consistently work with multiple chunks via CommonsChunkPlugin
chunksSortMode: 'dependency'
}),
new HtmlWebpackPlugin({
filename: config.build.internal,
template: path.resolve(__dirname, '../errors/500.html'),
inject: true,
favicon: resolveApp('favicon.ico'),
minify: {
removeComments: true,
collapseWhitespace: true,
removeAttributeQuotes: true
},
chunks: [],
// necessary to consistently work with multiple chunks via CommonsChunkPlugin
chunksSortMode: 'dependency'
}),
new HtmlWebpackPlugin({
filename: config.build.licenses,
template: 'licenses.html',
inject: true,
minify: {
removeComments: true,
collapseWhitespace: true,
removeAttributeQuotes: true
},
chunks: [],
// necessary to consistently work with multiple chunks via CommonsChunkPlugin
chunksSortMode: 'dependency'
}),
// keep module.id stable when vender modules does not change
new webpack.HashedModuleIdsPlugin(),
// enable scope hoisting
new webpack.optimize.ModuleConcatenationPlugin(),
// , 。
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
}),
// ,
new webpack.optimize.CommonsChunkPlugin({
name: 'app',
async: 'vendor-async',
children: true,
minChunks: 3
}),
// , dist
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
})
)
}
// Content-Encoding
if (config.build.bundleAnalyzerReport) {
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
webpackConfig.plugins.push(new BundleAnalyzerPlugin())
}
module.exports = webpackConfig
이상 이 바로 본 고의 모든 내용 입 니 다.여러분 의 학습 에 도움 이 되 고 저 희 를 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
【Vue.js】Xserver에 Vue CLI로 만든 초간이 페이지를 배포해 보았다.Vue CLI를 사용한 포트폴리오 제작은 처음이었기 때문에, 일단 제작에 착수하기 전에 배포가 가능한지 시도해 보았습니다. (모처럼 만들었는데 배포할 수 없다니 된다면 너무 슬프니까...웃음) 결론, 비교적 간단하게...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.