vue-cli在webpack的配置文件探究

40次阅读

共计 18562 个字符,预计需要花费 47 分钟才能阅读完成。

我们在构建一个 vue 项目的时候是不是一顿操作猛如虎啊?npm install vue-cli -g
vue init webpack vue-demo
npm install
npm run dev 然后稍等一小会儿,咱们就能在浏览器看到了咱们的界面啦
实际操作项目里面咱们可能需要修改一些配置项才能满足咱们自己项目的需求
先看看 vue 项目初始化的文件目录结构:
├─build
├─config
├─dist
├─node_modules
├─src
│ ├─assets
│ ├─components
│ ├─router
│ ├─App.vue
│ ├─main.js
├─static
├─.babelrc
├─.editorconfig
├─.gitignore
├─.postcssrc.js
├─index.html
├─package-lock.json
├─package.json
└─README.md

来看看重要的文件,按我理解的顺序来啊:
1.package.json
项目作为一个大家庭,每个文件都各司其职。package.json 来制定名单,需要哪些 npm 包来参与到项目中来,npm install 命令根据这个配置文件增减来管理本地的安装包。
这里面存放着我们项目的配置项,比如引入的依赖、项目作者、项目版本、项目编译启动的命令(放到 script 下面的)、还有就是 dependencies 和 devDependencies、node 和 npm 的信息、浏览器版本信息等等。
这儿说一下这个 dependencies 和 devDependencies
我们在使用 npm install 安装模块或插件的时候,有两种命令把他们写入到 package.json 文件里面去,比如:
–save-dev 安装的 插件,被写入到 devDependencies 对象里面去
–save 安装的 插件,被写入到 dependencies 对象里面去

package.json 文件里面的 devDependencies 和 dependencies 对象有什么区别呢?
devDependencies 里面的插件只用于开发环境,不用于生产环境
dependencies 是需要发布到生产环境的。

npm install 会安装两个依赖 npm install packagename 只安装 dependencies 的依赖 npm install packagename –dev 会安装 devDependencies 的依赖
如果你只是单纯的使用这个包而不需要进行一些改动测试之类的,只安装 dependencies 而不安装 devDependencies。执行:npm install –production
file-loader 和 url-loader 的区别:
以图片为例,file-loader 可对图片进行压缩,但是还是通过文件路径进行引入,当 http 请求增多时会降低页面性能,而 url-loader 通过设定 limit 参数,小于 limit 字节的图片会被转成 base64 的文件,大于 limit 字节的将进行图片压缩的操作。总而言之,url-loader 是 file-loader 的上层封装。
2、.postcssrc.js
.postcssrc.js 文件其实是 postcss-loader 包的一个配置,在 webpack 的旧版本可以直接在 webpack.config.js 中配置,现版本中 postcss 的文档示例独立出.postcssrc.js,里面写进去需要使用到的插件。
module.exports = {
“plugins”: {
“postcss-import”: {},
“postcss-url”: {},
“autoprefixer”: {}
}
}
关于这个 postcss,去搜一下吧,这玩意儿我估摸着以后肯定会成为继 scss 和 less 后最火的一个 css 预处理
咳咳,觉得自己英语能过关的去这儿看看 postcss
咱们这还是有中文的,哈哈 postcss
3、.babelrc
要了解这玩意儿,就内容超级多了,babel 在 vue 项目里面就是为了把 ES6 的语法转换成 ES5,废话不多说,咱们还是给链接把,笑哭了 babel 官方网站 去这儿直接了解这个神奇的东东
4、src 内文件
我们开发的代码都存放在 src 目录下,根据需要我们通常会再建一些文件夹。比如 pages 的文件夹,用来存放页面让 components 文件夹专门做好组件的工作;api 文件夹,来封装请求的参数和方法;store 文件夹,使用 vuex 来作为 vue 的状态管理工具,我也常叫它作前端的数据库等。
assets 文件:脚手架自动回放入一个图片在里面作为初始页面的 logo。平常我们使用的时候会在里面建立 js,css,img,fonts 等文件夹,作为静态资源调用

components 文件夹:用来存放组件,合理地使用组件可以高效地实现复用等功能,从而更好地开发项目。一般情况下比如创建头部组件的时候,我们会新建一个 header 的文件夹,然后再新建一个 header.vue 的文件夹

router 文件夹:该文件夹下有一个叫 index.js 文件,用于实现页面的路由跳转,具体使用请点击→vue-router 传送门

App.vue:作为我们的主组件,可通过使用开放入口让其他的页面组件得以显示。

main.js:作为我们的入口文件,主要作用是初始化 vue 实例并使用需要的插件,小型项目省略 router 时可放在该处

5、其他文件
.editorconfig:编辑器的配置文件

.gitignore:忽略 git 提交的一个文件,配置之后提交时将不会加载忽略的文件

index.html:页面入口,经过编译之后的代码将插入到这来。

package.lock.json:锁定安装时的包的版本号,并且需要上传到 git,以保证其他人在 npm install 时大家的依赖能保证一致

README.md:可此填写项目介绍

node_modules:根据 package.json 安装时候生成的的依赖(安装包)

.eslint 相关文件,存放项目的编写格式规范,例如缩进,末尾分号,单双引号,对项目开发很有帮助,特别是大项目,规范所有人的开发,减少代码规范冲突

config 文件夹
├─config
│ ├─dev.env.js
│ ├─index.js
│ ├─prod.env.js

1、config/dev.env.js
config 内的文件其实是服务于 build 的,大部分是定义一个变量 export 出去
‘use strict’
// 采用严格模式
const merge = require(‘webpack-merge’)
const prodEnv = require(‘./prod.env’)
//webpack-merge 提供了一个合并函数,它将数组和合并对象创建一个新对象。
// 如果遇到函数,它将执行它们,通过算法运行结果,然后再次将返回的值封装在函数中. 这边将 dev 和 prod 进行合并
module.exports = merge(prodEnv, {
NODE_ENV: ‘”development”‘
})

2、config/prod.env.js
当开发是调取 dev.env.js 的开发环境配置,发布时调用 prod.env.js 的生产环境配置
‘use strict’
module.exports = {
NODE_ENV: ‘”production”‘
}
3、config/index.js
‘use strict’
const path = require(‘path’)
module.exports = {
dev: {
// 开发环境下面的配置
assetsSubDirectory: ‘static’, // 子目录,一般存放 css,js,image 等文件
assetsPublicPath: ‘/’, // 根目录
proxyTable: {}, // 可利用该属性解决跨域的问题(axios)
host: ‘localhost’, // 地址
port: 8080, // 端口号设置,端口号占用出现问题可在此处修改
autoOpenBrowser: false, // 是否在编译(输入命令行 npm run dev)后打开 http://localhost:8080/ 页面,以前配置为 true,近些版本改为 false,个人偏向习惯自动打开页面
errorOverlay: true, // 浏览器错误提示
notifyOnErrors: true, // 跨平台错误提示
poll: false, // 使用文件系统 (file system) 获取文件改动的通知 devServer.watchOptions
devtool: ‘cheap-module-eval-source-map’,// 增加调试,该属性为原始源代码(仅限行)不可在生产环境中使用
cacheBusting: true, // 使缓存失效
cssSourceMap: true // 代码压缩后进行调 bug 定位将非常困难,于是引入 sourcemap 记录压缩前后的位置信息记录,当产生错误时直接定位到未压缩前的位置,将大大的方便我们调试
},
build: {// 生产环境下面的配置
index: path.resolve(__dirname, ‘../dist/index.html’), //index 编译后生成的位置和名字,根据需要改变后缀,比如 index.php
assetsRoot: path.resolve(__dirname, ‘../dist’), // 编译后存放生成环境代码的位置
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
│ ├─build.js
│ ├─check-versions.js
│ ├─utils.js
│ ├─vue-loader.conf.js
│ ├─webpack.base.conf.js
│ ├─webpack.dev.conf.js
│ ├─webpack.prod.conf.js

1、build/build.js
‘use strict’
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’)
// 调用 start 的方法实现加载动画,优化用户体验
const spinner = ora(‘building for production…’)
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, // 如果您使用的是 ts-loader,将其设置为 true 将导致在构建期间出现 TypeScript 错误
chunks: false,
chunkModules: false
}) + ‘\n\n’)

if (stats.hasErrors()) {
console.log(chalk.red(‘ 构建失败并出现错误 \n’))
process.exit(1)
}

console.log(chalk.cyan(‘ 构建成功.\n’))
console.log(chalk.yellow(
‘Tip: 构建的文件旨在通过 HTTP 服务器提供.\n’ + ‘ 正在打开 index.html 在 file:// won\’t work.\n’
))
})
})

2、build/check-version.js
该文件用于检测 node 和 npm 的版本,实现版本依赖
‘use strict’
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)
}
}

3、build/utils.js
utils 是工具的意思,是一个用来处理 css 的文件。
‘use strict’
const path = require(‘path’)
const config = require(‘../config’)
const ExtractTextPlugin = require(‘extract-text-webpack-plugin’)
const packageConfig = require(‘../package.json’)
// 导出文件的位置,根据环境判断开发环境和生产环境,为 config 文件中 index.js 文件中定义的 build.assetsSubDirectory 或 dev.assetsSubDirectory
exports.assetsPath = function (_path) {
const assetsSubDirectory = process.env.NODE_ENV === ‘production’
? config.build.assetsSubDirectory
: config.dev.assetsSubDirectory
//Node.js path 模块提供了一些用于处理文件路径的小工具
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
})
})
}

//ExtractTextPlugin 可提取出文本,代表首先使用上面处理的 loaders,当未能正确引入时使用 vue-style-loader
if (options.extract) {
return ExtractTextPlugin.extract({
use: loaders,
fallback: ‘vue-style-loader’
})
} 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’)
})
}
}

path.posix:提供对路径方法的 POSIX(可移植性操作系统接口)特定实现的访问,即可跨平台,区别于 win32。
path.join:用于连接路径,会正确使用当前系统的路径分隔符,Unix 系统是 ”/”,Windows 系统是 ””

4、vue-loader.conf.js
该文件的主要作用就是处理.vue 文件,解析这个文件中的每个语言块(template、script、style), 转换成 js 可用的 js 模块。
‘use strict’
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’
}
}

5、webpack.base.conf.js
webpack.base.conf.js 是开发和生产共同使用提出来的基础配置文件,主要实现配制入口,配置输出环境,配置模块 resolve 和插件等。
‘use strict’
const path = require(‘path’)
const utils = require(‘./utils’)
const config = require(‘../config’)
const vueLoaderConfig = require(‘./vue-loader.conf’)

function resolve (dir) {
// 拼接出绝对路径
return path.join(__dirname, ‘..’, dir)
}
// 添加 eslint 过滤
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 = {
//path.join 将路径片段进行拼接,而 path.resolve 将以 / 开始的路径片段作为根目录,在此之前的路径将会被丢弃
//path.join(‘/a’, ‘/b’) // ‘a/b’,path.resolve(‘/a’, ‘/b’) // ‘/b’
context: path.resolve(__dirname, ‘../’),
// 配置入口,默认为单页面所以只有 app 一个入口
entry: {
app: ‘./src/main.js’
},
// 配置出口,默认是 /dist 作为目标文件夹的路径
output: {
path: config.build.assetsRoot,
filename: ‘[name].js’,
publicPath: process.env.NODE_ENV === ‘production’
? config.build.assetsPublicPath
: config.dev.assetsPublicPath
},
resolve: {
// 自动的扩展后缀,比如一个 js 文件,则引用时书写可不要写.js
extensions: [‘.js’, ‘.vue’, ‘.json’],
// 创建路径的别名,比如增加 ’components’: resolve(‘src/components’)等
alias: {
‘vue$’: ‘vue/dist/vue.esm.js’,
‘@’: resolve(‘src’),
}
},
// 使用插件配置相应文件的处理方法
module: {
rules: [
…(config.dev.useEslint ? [createLintingRule()] : []), // 加载 eslint 代码规范规则
// 使用 vue-loader 将 vue 文件转化成 js 的模块
{
test: /\.vue$/,
loader: ‘vue-loader’,
options: vueLoaderConfig
},
//js 文件需要通过 babel-loader 进行编译成 es5 文件以及压缩等操作
{
test: /\.js$/,
loader: ‘babel-loader’,
include: [resolve(‘src’), resolve(‘test’), resolve(‘node_modules/webpack-dev-server/client’)]
},
// 图片、音像、字体都使用 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]’)
}
}
]
},
// 以下选项是 Node.js 全局变量或模块,这里主要是防止 webpack 注入一些 Node.js 的东西到 vue 中
node: {
// 防止 webpack 注入无用的 setImmediate polyfill,因为 Vue 源包含它(虽然只有它是原生的才使用它)
setImmediate: false,
// 防止 webpack 将模拟注入到对客户端没有意义的 Node 本机模块
dgram: ’empty’,
fs: ’empty’,
net: ’empty’,
tls: ’empty’,
child_process: ’empty’
}
}

6、webpack.dev.conf.js
‘use strict’
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 path = require(‘path’)
const baseWebpackConfig = require(‘./webpack.base.conf’)
const CopyWebpackPlugin = require(‘copy-webpack-plugin’)
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)

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: {
clientLogLevel: ‘warning’, // 控制台显示的选项有 none, error, warning 或者 info
// 当使用 HTML5 History API 时,任意的 404 响应都可能需要被替代为 index.html
historyApiFallback: {
rewrites: [
{from: /.*/, to: path.posix.join(config.dev.assetsPublicPath, ‘index.html’) },
],
},
hot: true, // 热加载
contentBase: false, // since we use CopyWebpackPlugin.
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, // warning 和 error 都要显示
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
}),
// 复制插件
new CopyWebpackPlugin([
{
from: path.resolve(__dirname, ‘../static’),
to: config.dev.assetsSubDirectory,
ignore: [‘.*’] // 忽略.* 的文件
}
])
]
})

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
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)
}
})
})

7、webpack.prod.conf.js
‘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 = require(‘../config/prod.env’)

const webpackConfig = merge(baseWebpackConfig, {
module: {
// 调用 utils.styleLoaders 的方法
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
}),
// 抽取文本。比如打包之后的 index 页面有 style 插入,就是这个插件抽取出来的,减少请求
new ExtractTextPlugin({
filename: utils.assetsPath(‘css/[name].[contenthash].css’),
// 将以下选项设置为“false”将不会从 codesplit 块中提取 CSS
// 当 webpack 加载了 codesplit 块时,他们的 CSS 将使用 style-loader 动态插入
// 它目前设置为“true”,因为我们看到源代码包含在 codesplit 包中,当它是“false”增加文件大小时:https://github.com/vuejs-templates/webpack/issues/1110
allChunks: true,
}),
// 压缩提取的 CSS。我们正在使用此插件,以便可以减少来自不同组件的可能重复的 CSS
new OptimizeCSSPlugin({
cssProcessorOptions: config.build.productionSourceMap
? {safe: true, map: { inline: false} }
: {safe: true}
}),
// 使用正确的资产哈希生成 dist index.html 以进行缓存.
// 您可以通过编辑 /index.html 来自定义输出
// 请参阅 https://github.com/ampedandwired/html-webpack-plugin
new HtmlWebpackPlugin({
filename: config.build.index,
template: ‘index.html’,
inject: true,
minify: {
removeComments: true, // 删除注释
collapseWhitespace: true, // 删除空格
removeAttributeQuotes: true // 删除属性的引号
// 更多属性参见:https://github.com/kangax/html-minifier#options-quick-reference
},
// 通过 CommonsChunkPlugin 持续使用多个块的必要条件
chunksSortMode: ‘dependency’ // 模块排序,按照我们需要的顺序排序
}),
// 当供应商模块没有改变时,保持 module.id 稳定
new webpack.HashedModuleIdsPlugin(),
// 启用域限制
new webpack.optimize.ModuleConcatenationPlugin(),
// 将供应商 js 拆分为自己的文件
new webpack.optimize.CommonsChunkPlugin({
name: ‘vendor’,
minChunks (module) {
// node_modules 中的任何必需模块都将解压缩到供应商
return (
module.resource &&
/\.js$/.test(module.resource) &&
module.resource.indexOf(
path.join(__dirname, ‘../node_modules’)
) === 0
)
}
}),
// 将 webpack 运行时和模块清单提取到其自己的文件中,以防止在更新应用程序包时更新供应商哈希
new webpack.optimize.CommonsChunkPlugin({
name: ‘manifest’,
minChunks: Infinity
}),
// 此实例从代码拆分块中提取共享块,并将它们捆绑在一个单独的块中,类似于供应商块,请参阅: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
}),

// 复制自定义静态资源到 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
})
)
}

if (config.build.bundleAnalyzerReport) {
const BundleAnalyzerPlugin = require(‘webpack-bundle-analyzer’).BundleAnalyzerPlugin
webpackConfig.plugins.push(new BundleAnalyzerPlugin())
}

module.exports = webpackConfig

全是代码,代码全是项目模块的东西。估计有好多小伙伴儿看一点点就关了,能看完的,给你比心哦,哈哈哈
可以参考那本书叫《深入浅出 webpack》

正文完
 0