Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

vue-cli 2.x初始化配置解析 #15

Open
wolfdu opened this issue Dec 18, 2017 · 0 comments
Open

vue-cli 2.x初始化配置解析 #15

wolfdu opened this issue Dec 18, 2017 · 0 comments

Comments

@wolfdu
Copy link
Owner

wolfdu commented Dec 18, 2017

https://wolfdu.fun/post?postId=5a142002c7ad1346411b7250

v

最近使用vue-cli搭建了blog,除了test没有使用脚手架(因为还没有写test😹)基本其他所有脚手架提供的功能全部使用到了,免去了前期搭建框架的很多坑,让使用vue搭建小项目的同学更方便入坑,当然也错过了学习的机会特别是webpack这一块的内容,所以本着知其所以然的态度,然我们来刨刨坑⛏

vue-cli具体是个啥呢?

答:他是vue项目的简单脚手架,就是工地的脚手架,他帮你架好后你就可以认真搬砖了😂

毕竟是别人帮你搭建的脚手架,总觉的不安全,我们就来好好检查检查,他到底给我们安装了些顺马东西。。。

以下分析的初始化脚手架来自于vue-templaes/webpack

我们先来看看目录结构:

	.
	├── build
	│   ├── build.js
	
	│   ├── check-versions.js
	│   ├── utils.js
	│   ├── vue-loader.conf.js
	│   ├── webpack.base.conf.js
	│   ├── webpack.dev.conf.js
	│   └── webpack.prod.conf.js
	├── config
	│   ├── dev.env.js
	│   ├── index.js
	│   └── prod.env.js
	├── src
	│   ├── assets
	│   │   └── logo.png
	│   ├── components
	│   │   └── Hello.vue
	│   ├── App.vue
	│   └── main.js
	├── static
	├── .babelrc
	├── .editorconfig
	├── .eslintignore
	├── .eslintrc.js
	├──.postcssrc.js
	├── README.md
	├── index.html
	└── package.json

我们先来看看ESLint的相关配置吧,毕竟在第一次使用的时候曾让我怀疑人生👺

1 ESLint

ESLint是一个检查JavaScript代码错误和统一代码风格的工具。团队开发中使用效果甚好😏
项目中关于ESLint的文件有两个.eslintignore和.eslintrc.js

1.1 .eslintignore

/build/
/config/
/dist/
/*.js

顾名思义,该配置会忽略以上文件不进行代码格式的检查。

1.2 .eslintrc.js

	// https://eslint.org/docs/user-guide/configuring

	//ESLint会自动查找并读取该文件进行配置
	module.exports = {
		root: true, // 设置当前文件为该目录下配置文件,可在多项目中实现个性化配置
		parser: 'babel-eslint', // 指定解析器
		parserOptions: {// 解析器选项,可以选择es版本如es6:ecmaVersion:'6'
			sourceType: 'module' // 代码位于ECMAScript模
		},
		env: {// 环境配置
			browser: true,// 启用浏览器环境
		},
		// https://github.com/standard/standard/blob/master/docs/RULES-en.md
		extends: 'standard',// 扩展启用standard规则集
		// required to lint *.vue files
		plugins: [// 配置插件支持各种文件语法
			'html'
		],
		// add your custom rules here
		'rules': {// 自定义规则
			// allow paren-less arrow functions
			'arrow-parens': 0,
			// allow async-await
			'generator-star-spacing': 0,
			// allow debugger during development
			'no-debugger': process.env.NODE_ENV === 'production' ? 2 : 0
		}
	}

standard规范传送门

2 .editorconfig

Editorconfig是助于开发人员在不同的编辑器或IDE下保持编码风格一致。

#设置当前文件为顶级config
root = true

#所有文件适用以下规则
[*]
#使用utf-8编码
charset = utf-8
#使用空格缩进
indent_style = space
#缩进数为2
indent_size = 2
#指定换行符格式, 一般由lf(line feed),cr(carriage return),crlf(carriage return line feed)
end_of_line = lf
#是否在文件最后插入空行
insert_final_newline = true
#是否trim掉行尾的空格
trim_trailing_whitespace = true

3 .babelrc

Babel是一个可以将ES6代码转换为ES5的编译器。

	{
		"presets": [// 设置转码规则,使用的时候需要安装对应的插件,对应babel-preset-xxx,例如下面的配置babel-preset-env
			["env", {// options
				"modules": false,// 不会转换模块
				"targets": {
					"browsers": ["> 1%", "last 2 versions", "not ie <= 8"] 
					// 使用BrowserList(https://github.com/ai/browserslist)表查询选择浏览器
				}
			}],
			"stage-2"
			// stage-x和es2015等有些类似,但是它是按照JavaScript的提案阶段区分的,
			//一共有5个阶段。而数字越小,阶段越靠后,存在依赖关系。也就是说stage-0是包括stage-1的
		],
		"plugins": ["transform-runtime"],// 插件,该插件解决编译中产生的重复的helper函数,减小代码体积
		"env": {// 特定环境下执行编译规则
			"test": {// env为test时的编译规则
				"presets": ["env", "stage-2"],// 同上
				"plugins": ["istanbul"]// 测试使用插件
			}
		}
	}

相关文档:

4 webpack

终极大Boss😈,可以发现脚手架中webpack相关的配置文件占了大部分篇幅,接下来让我们看看它都干了些啥。

这里我们从一定的场景切入,当我们初始化好项目后首先会迫不及待的看看他运行起来是效果。

我们会进行如下操作:

	npm run start
	
	// 控制台会告诉我们
	Your application is running here: http://localhost:8080

打开package.json我们会发现这样一段代码:

	"scripts": {
			"dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js",
			"start": "npm run dev",
			"lint": "eslint --ext .js,.vue src",
			"build": "node build/build.js"
		}

我们可以发现实际执行的是如下代码:

npm run dev

webpack-dev-server --inline --progress --config build/webpack.dev.conf.js

webpack-dev-server能够用于快速开发,会帮我起一个Express服务,以便调试前端代码。

这样我们就找到我们的切入点了webpack-dev-conf.js(暂时不去关注前面的--iline和--progress)

4.1 webpack.dev.conf.js

	'use strict'
	// 加载工具类
	const utils = require('./utils')
	// 加载webpack
	const webpack = require('webpack')
	// 加载config/index.js
	const config = require('../config')
	// 加载webpack-merge
	const merge = require('webpack-merge')
	// 加载webpack base config文件
	const baseWebpackConfig = require('./webpack.base.conf')
	// 根据配置生成一个HTML文件
	const HtmlWebpackPlugin = require('html-webpack-plugin')
	// 打包日志展示插件,友好的展示日志
	const FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin')
	// 查找开放端口工具
	const portfinder = require('portfinder')

	// dev环境下的webpackConfig,merge baseWebpackConfig
	const devWebpackConfig = merge(baseWebpackConfig, {
		module: {
			// 加载样式文件的装载器(loader)
			rules: utils.styleLoaders({ sourceMap: config.dev.cssSourceMap, usePostCSS: true })
		},
		// cheap-module-eval-source-map is faster for development
		// 为打包文件加入sourceMap信息,当前使用的是“eval-source-map”
		devtool: config.dev.devtool,

		// these devServer options should be customized in /config/index.js
		// https://doc.webpack-china.org/configuration/dev-server/
		devServer: {// webpack-dev-server配置选项
			clientLogLevel: 'warning',// 用于在DevTools控制台现在消息,默认为“info”
			historyApiFallback: true, // 任意的404响应都会替代为index.html
			hot: true,// 启用模块热加载
			host: process.env.HOST || config.dev.host,// 设置启动服务host
			port: process.env.PORT || config.dev.port,// 设置启动服务port
			open: config.dev.autoOpenBrowser,// 是否启动后打开浏览器
			overlay: config.dev.errorOverlay ? {// 当编译出现错误时是否在浏览器展示warning或errors信息
				warnings: false,
				errors: true,
			} : false,
			publicPath: config.dev.assetsPublicPath,// 设置路径,服务器可以通过该路径访问打包文件
			proxy: config.dev.proxyTable,// 使用了 http-proxy-middleware 可以配置后端服务代理
			quiet: true, 
			// necessary for FriendlyErrorsPlugin,启用 quiet 后,除了初始启动信息之外的任何内容都不会被打印到控制台。
			//这也意味着来自 webpack 的错误或警告在控制台不可见。
			
			watchOptions: {// 监视文件相关的控制选项
				poll: config.dev.poll,// 通过传递 true 开启 polling,或者指定毫秒为单位进行轮询。
			}
		},
		plugins: [
			new webpack.DefinePlugin({// 编译时配置修改全局变量
				'process.env': require('../config/dev.env')// 获取运行环境变量
			}),
			new webpack.HotModuleReplacementPlugin(),
			// 模块热替换功能会在应用程序运行过程中替换、添加或删除模块,而无需重新加载页面
			
			new webpack.NamedModulesPlugin(), 
			// HMR shows correct file names in console on update.使用模块的相对路径作为模块的 id
			
			new webpack.NoEmitOnErrorsPlugin(),
			// 在编译出现错误时,使用 NoEmitOnErrorsPlugin 来跳过输出阶段。这样可以确保输出资源不会包含错误
			// https://github.com/jantimon/html-webpack-plugin#configuration
			new HtmlWebpackPlugin({
				filename: 'index.html',
				template: 'index.html',
				inject: true
			}),
		]
	})

	module.exports = new Promise((resolve, reject) => {
		// 设置端口
		portfinder.basePort = process.env.PORT || config.dev.port
		portfinder.getPort((err, port) => {
			if (err) {
				reject(err)
			} else {
				// 发布使用新设置的端口
				process.env.PORT = port
				// 将端口信息设置到DevServer中
				devWebpackConfig.devServer.port = port

				// Add FriendlyErrorsPlugin
				devWebpackConfig.plugins.push(new FriendlyErrorsPlugin({
					compilationSuccessInfo: {
						messages: [`Your application is running here: http://${config.dev.host}:${port}`],
					},
					onErrors: config.dev.notifyOnErrors
					? utils.createNotifierCallback()
					: undefined
				}))

				resolve(devWebpackConfig)
			}
		})
	})

看完dev环境下的配置文件后,或许最大疑问是merge的baseWebpackConfig是什么样子的呢?
不说话自己看🙀

4.2 webpack.base.conf.js

	'use strict'
	// node文件路径工具
	const path = require('path')
	// 加载工具类
	const utils = require('./utils')
	// 加载config/index.js
	const config = require('../config')
	// 加载vue-loader配置文件
	const vueLoaderConfig = require('./vue-loader.conf')

	function resolve (dir) {// 获取
		return path.join(__dirname, '..', dir)
	}

	module.exports = {
		context: path.resolve(__dirname, '../'),// 设置基础目录,用于解析入口起点
		entry: {// 应用程序起点入口
			app: './src/main.js'
		},
		output: {// 指示 webpack 如何去输出、以及在哪里输出你的打包文件
			path: config.build.assetsRoot,// output 目录对应一个绝对路径
			filename: '[name].js',// 此选项决定了每个输出 bundle 的名称,这里使用入口名称作为文件名
			publicPath: process.env.NODE_ENV === 'production'// 设置publicPath
				? config.build.assetsPublicPath
				: config.dev.assetsPublicPath
		},
		resolve: {// 选项能设置模块如何被解析
			extensions: ['.js', '.vue', '.json'],// 自动解析确定的扩展。使用时就可以不用带扩展名了
			alias: {// 创建 import 或 require 的别名,来确保模块引入变得更简单
				'vue$': 'vue/dist/vue.esm.js',
				'@': resolve('src'),
			}
		},
		module: {// 选项决定了如何处理项目中的不同类型的模块
			rules: [// 创建模块时,匹配请求的规则数组
				...(config.dev.useEslint? [{// 配置使用eslint相关配置
					test: /\.(js|vue)$/,// 匹配条件,接受正则表达式
					loader: 'eslint-loader',// 使用eslint loader
					enforce: 'pre',// 指定 loader 种类;pre--预先加载
					include: [resolve('src'), resolve('test')],// 需要匹配规则的内容
					options: {
						formatter: require('eslint-friendly-formatter'),// 使用eslint-friendly-formatter格式化代码
						emitWarning: !config.dev.showEslintErrorsInOverlay// 是否显示eslint的error和warning信息
					}
				}] : []),
				{
					test: /\.vue$/,
					loader: 'vue-loader',
					options: vueLoaderConfig // vue-loader.conf配置文件
				},
				{
					test: /\.js$/,
					loader: 'babel-loader',
					include: [resolve('src'), resolve('test')]
				},
				{
					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]')
					}
				}
			]
		}
	}

4.3 vue-loader.conf.js

	'use strict'
	// 加载工具类
	const utils = require('./utils')
	// 加载config/index.js
	const config = require('../config')
	// 判断是否为生成环境
	const isProduction = process.env.NODE_ENV === 'production'
	// 如果是生成环境则需要加载sourceMap
	const sourceMapEnabled = isProduction
		? config.build.productionSourceMap
		: config.dev.cssSourceMap


	module.exports = {
		loaders: utils.cssLoaders({// 获取样式文件的装载器
			sourceMap: sourceMapEnabled,// 是否加载sourceMap
			extract: isProduction // 是否抽取样式文件
		}),
		cssSourceMap: sourceMapEnabled,// 是否加载样式sourceMap
		// 在模版编译过程中,编译器可以将某些属性,如 src 路径,转换为 require 调用,以便目标资源可以由 Webpack 处理。
		// 默认配置会转换 <img> 标签上的 src 属性和 SVG 的 <image> 标签上的 xlink:href 属性。
		transformToRequire: {
			video: 'src',
			source: 'src',
			img: 'src',
			image: 'xlink:href'
		}
	}

当我们开发完成后,我们会将开发代码进行打包以减小项目代码的体积方便我们部署到服务器。

此时我们需要执行如下命令:

	npm run build
	
	// 具体执行的内容是
	node build/build.js
	```

那我们先看看build.js内有什么内容:

### 4.4 build.js

```js
	'use strict'
	// 检查node和npm版本
	require('./check-versions')()
	// 设置node运行环境参数
	process.env.NODE_ENV = 'production'
	// loading插件
	const ora = require('ora')
	// 用来执行rm -rf的包
	const rm = require('rimraf')
	const path = require('path')
	// 可以修改控制太字符样式的包
	const chalk = require('chalk')
	const webpack = require('webpack')
	const config = require('../config')
	// 生产环境打包文件
	const webpackConfig = require('./webpack.prod.conf')

	const spinner = ora('building for production...')
	spinner.start()
	// 先删除之前打包的内容,然后进行打包
	rm(path.join(config.build.assetsRoot, config.build.assetsSubDirectory), err => {
		if (err) throw err
		// 开始编译打包
		webpack(webpackConfig, function (err, stats) {// 回调函数
			spinner.stop()
			if (err) throw err
			process.stdout.write(stats.toString({
				colors: true,
				modules: false,
				children: false,
				chunks: false,
				chunkModules: false
			}) + '\n\n')

			if (stats.hasErrors()) {
				console.log(chalk.red('  Build failed with errors.\n'))
				process.exit(1)
			}

			console.log(chalk.cyan('  Build complete.\n'))
			console.log(chalk.yellow(
				'  Tip: built files are meant to be served over an HTTP server.\n' +
				'  Opening index.html over file:// won\'t work.\n'
			))
		})
	})
	```

### 4.5 webpack.prod.conf.js

```js
	'use strict'
	// node文件路径工具
	const path = require('path')
	// 加载工具类
	const utils = require('./utils')
	const webpack = require('webpack')
	// 加载config/index.js
	const config = require('../config')
	const merge = require('webpack-merge')
	// 打包base config文件
	const baseWebpackConfig = require('./webpack.base.conf')
	// 将单个文件或者文件夹复制到构建目录插件
	const CopyWebpackPlugin = require('copy-webpack-plugin')
	// 根据配置生成一个HTML文件
	const HtmlWebpackPlugin = require('html-webpack-plugin')
	// 将css样式抽取到独立的文件中
	const ExtractTextPlugin = require('extract-text-webpack-plugin')
	// 压缩提取出的css文件,解决css复用的问题
	const OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin')
	// 获取prod配置文件
	const env = require('../config/prod.env')
	// prod环境下的webpackConfig,merge baseWebpackConfig
	const webpackConfig = merge(baseWebpackConfig, {
		module: {
			rules: utils.styleLoaders({// 加载prod下样式文件的装载器(loader)可以对比dev两套环境下的区别
				sourceMap: config.build.productionSourceMap,
				extract: true,
				usePostCSS: true
			})
		},
		// 为打包文件加入sourceMap信息,当前使用的是“#source-map”
		devtool: config.build.productionSourceMap ? config.build.devtool : false,
		output: {// 指示 webpack 如何去输出、以及在哪里输出你的打包文件
			path: config.build.assetsRoot,
			filename: utils.assetsPath('js/[name].[chunkhash].js'),// 根据文件名以及路径生成打包文件名
			chunkFilename: utils.assetsPath('js/[name].[chunkhash].js')
		},
		plugins: [
			// http://vuejs.github.io/vue-loader/en/workflow/production.html
			new webpack.DefinePlugin({// 编译时配置修改全局变量
				'process.env': env
			}),
			// UglifyJs do not support ES6+,
			//you can also use babel-minify for better treeshaking: https://github.com/babel/minify
			new webpack.optimize.UglifyJsPlugin({// 使用Uglify压缩js代码
				compress: {
					warnings: false
				},
				sourceMap: config.build.productionSourceMap,
				parallel: true// 是否并行运行
			}),
			// extract css into its own file
			new ExtractTextPlugin({// 抽取css样式文件
				filename: utils.assetsPath('css/[name].[contenthash].css'),
				// set the following option to `true` if you want to extract CSS from
				// codesplit chunks into this main css file as well.
				// This will result in *all* of your app's CSS being loaded upfront.
				allChunks: false,
			}),
			// Compress extracted CSS. We are using this plugin so that possible
			// duplicated CSS from different components can be deduped.
			new OptimizeCSSPlugin({// 压缩提取的css文件,一遍不同组件复用
				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: config.build.index,
				template: 'index.html',
				inject: true,
				minify: {// 压缩HTML代码 https://github.com/kangax/html-minifier#options-quick-reference
					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'
			}),
			// 生成模块相对路径生成hash作为模块id
			// keep module.id stable when vender 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: function (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) {// 启用gzip压缩相应配置
		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

至此我们整个脚手架使用场景都使用完了,但是好像还有一个出镜率比较高的文件文件我们还没有看那就是
它👇

4.6 utils.js

	'use strict'
	// node文件路径工具
	const path = require('path')
	// 获取config/index.js
	const config = require('../config')
	// 将css样式抽取到独立的文件中
	const ExtractTextPlugin = require('extract-text-webpack-plugin')
	// 加载package json文件
	const pkg = 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 || {}

		const cssLoader = {
			loader: 'css-loader',
			options: {
				sourceMap: options.sourceMap
			}
		}

		var postcssLoader = {
			loader: 'postcss-loader',
			options: {
				sourceMap: options.sourceMap
			}
		}

		// generate loader string to be used with extract text plugin
		// 通过loader, loaderOptions生成loader字符串
		function generateLoaders (loader, loaderOptions) {
			const loaders = options.usePostCSS ? [cssLoader, postcssLoader] : [cssLoader]
			if (loader) {
				loaders.push({
					loader: loader + '-loader',
					options: Object.assign({}, loaderOptions, {
						sourceMap: options.sourceMap
					})
				})
			}

			// Extract CSS when that option is specified
			// (which is the case during production build) 生产环境下抽取样式
			if (options.extract) {
				return ExtractTextPlugin.extract({
					use: loaders,// 指定的loader将样式转换为css
					fallback: 'vue-style-loader'// css样式没有被抽取的时候使用该loader
				})
			} else {
				return ['vue-style-loader'].concat(loaders)
			}
		}

		// https://vue-loader.vuejs.org/en/configurations/extract-css.html
		return {
			css: generateLoaders(),
			postcss: generateLoaders(),
			less: generateLoaders('less'),
			sass: generateLoaders('sass', { indentedSyntax: true }),
			scss: generateLoaders('sass'),
			stylus: generateLoaders('stylus'),
			styl: generateLoaders('stylus')
		}
	}

	// Generate loaders for standalone style files (outside of .vue)
	// 获取样式文件的装载器
	exports.styleLoaders = function (options) {
		const output = []
		const loaders = exports.cssLoaders(options)
		for (const extension in loaders) {
			const loader = loaders[extension]
			output.push({
				test: new RegExp('\\.' + extension + '$'),
				use: loader
			})
		}
		return output
	}

	// 设置提示信息内容
	exports.createNotifierCallback = function () {
		const notifier = require('node-notifier')

		return (severity, errors) => {
			if (severity !== 'error') {
				return
			}
			const error = errors[0]

			const filename = error.file.split('!').pop()
			notifier.notify({
				title: pkg.name,
				message: severity + ': ' + error.name,
				subtitle: filename || '',
				icon: path.join(__dirname, 'logo.png')
			})
		}
	}

参考文档:
webpack中文文档
npm
node-api

总结

😵终于整理完了,整个脚手架最为复杂的应该还是在webpack相关的配置,需要涉及到2套以上的环境配置。
但是其中大部分的配置,插件都可以从官方文档进行查阅,文档还是相当的给力的🖖

当前脚手架功能可以说已经十分完备了,但是具体的打包方案,还是要实际项目而定,分析打包结果再进行打包方案的优化。

你以为这样就完了吗!!!😱😱😱😱

开始搬砖吧^_^

若文中有知识整理错误或遗漏的地方请务必指出,非常感谢。如果对你有一丢丢帮助或引起你的思考,可以点赞鼓励一下作者=^_^=

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant