更详尽
https://blog.csdn.net/qq_24147051/article/details/81533739
config/dev.env.js
'use strict'
// 引入webpack-merge模块
const merge = require('webpack-merge')
// 引入刚才打开的prod.env.js
const proEnv = require('./prod.env')
// 引入webpack-merge后这个文件又引入了prod.env.js,接着就将prod.env.js的配置和新的配置,即指明开发环境(development)进行了merge。(我有点儿不太理解为什么要这样做,如果不merge直接写module.exports={NODE_ENV:'"development'}也是可以的,难道是为了优雅降级?)
module.exports = merge(proEnv,{
NODE_ENV:'"development"'
})
config/prod.env.js
'use strict'
module.exports = {
// 执行环境
NODE_ENV:'"production"'
}
config/index.js
/*
* @Author: yang
* @Date: 2020-10-12 12:58:04
* @LastEditors: yang
* @LastEditTime: 2020-10-14 13:41:33
* @FilePath: \新建文件夹 (4)\config\index.js
*/
'use strict'
const path = require('path')
module.exports = {
dev:{
// Path
assetsSubDirectory:'static',//子目录,一般存放css,js,image等文件
assetsPublicPath:'/',//根目录
proxyTable:{},//可利用该属性解决跨域的问题
//Various Dev Server settings
host:'localhost', //can be overwritten by progress.env.HOST 地址
port:8080,//可以被覆盖进程.env.PORT,如果端口正在使用,则将确定一个空闲端口 端口号设置,端口号占用出现问题可在此处修改
autoOpenBrowser:false,
errorOverlay:true,//浏览器错误提示
notifyOnErrors:true,//跨平台错误提示
poll:false,//使用文件系统(file system)获取文件改动的通知devServer.watchOptions
useEslint:true,//是否开启eslint 错误显示在console
showEslintErrorsInOverlay:false,//如果开启错误显示在浏览器中
devtool:'eval-source-map',
//使缓存失效
cacheBusting:true, //如果在devtools中调试vue文件遇到问题,把这个设置为false
cssSourceMap:false//代码压缩后进行bug定位困难,true开启 sourcemap记录压缩前后的位置信息记录,当产生错误可直接定位到未压缩前的位置,方便调试
},
build:{
// 生产环境下面的配置
index:path.resolve(__dirname,'../dist/index.html'),//index 编译后生成的位置和名字
assetsRoot:path.resolve(__dirname,'../dist'),//编译后存放生成环境代码的位置
assetsSubDirectory:'static',//js ,css img存放文件夹名
assetsPublicPath:'/',//发布的根目录,通常本地打包dist后打开文件会报错,此处修改为./。如果是上线的文件,可根据文件存放位置进行更改路径
productionSourceMao:true,//设置生产环境的 source map 开启与关闭。是否生成 sourceMap 文件
devtool:'#source-map',//生成.map文件
productionGzip: false,//unit的gzip命令用来压缩文件 gzip模式下需要压缩的文件的扩展名有css和js
productionGzipExtensions:['js','css'],
bundleAnalyzerReport:process.env.npm_config_report//build 对象的 bundleAnalyzerReport 优化打包之后文件提交的工具。是否开启打包后的分析报告
}
}
utils.js
// utils.js文件主要是用来处理各种css loader的,比如css-loader,less-loader等。
// 引入path模块
const path = require('path')
// 引入之前的config模块
const config = require('../config')
// 引入"extract-text-webpack-plugin"它的作用是打包后将生成的css文件通过link的方式引入到html中,如果不使用这个插件,那么css就打包到<head>的style中
const ExtractTextPlugin = require('extract-text-webpack-plugin')
// 引入package.json
const pkg = require('../package.json')
exports.assetsSubDirectory = function (_path) {
// 结合config文件的代码可以知道 当环境为生产环境时 assetsSubDirectory为static开发环境也是static
const assetsSubDirectory =
progress.env.NODE_ENV === 'production'
? config.build.assetsSubDirectory
: config.dev.assetsSubDirectory
// path.posix.join()是path.join的一种兼容写法 它的作用是路径的拼接 比如path.posix.join('/aa/s','bb')
return path.posix.join(assetsSubDirectory,_path)
}
// 用来生成Loader的函数,本身可以用在vue-loader的配置上,同时也是为styleLoader函数使用
exports.cssLoaders = function(options){
// 如果没有传参就默认空对象
options = options||{}
// 配置css-loader,css-loader可以让处理css中的@import或者url()
const cssLoader = {
loader:'css-loader',
options:{
sourceMap:options.sourceMap
}
}
// 配置postcss-loader,主要功能是补全css中的兼容性前缀 比如“-webkit-”等
var postcssLoader = {
loader:"postcss-laoder",
options:{
sourceMap:options.sourceMap
}
}
// 生成loader的私有方法
function generateLoaders(loader,loaderOptions){
// 参数的usePostCss属性是否为true 是就使用两个loader,否则只使用css-loader
const loaders = options.usePostCSS? [cssLoader,postcssLoader]:[cssLoader]
if(loader){
// 给generateLoaders传loader参数的话 比如less 或者sass 就将这个loader的配置传入到loaders数组中
loaders.push({
loader:loader+'-loader',
// Object.assign()是es6的语法 用来合并对象
options: Object.assign({}, loaderOptions, {
sourceMap: options.sourceMap
})
})
}
// 如果options参数的extract属性为true 即使用extract text plugin 将css抽成单独的文件 否则就将css写进style
if(options.extract){
return ExtractTextPlugin.extract({
use:loaders,
// vue-style-loader可以理解为vue版的style-loader 它可将css放进style中
fallback:'vue-style-loader'
})
}else{
return ['vue-style-loader'].concat('loaders')
}
}
return {
// 返回各种loader
css:generateLoaders(),
postcss:generateLoaders(),
less:generateLoaders('less'),
sass:generateLoaders('sass',{indentedSyntax:true}),
scss:generateLoaders('sass'),
stylus:generateLoaders('stylus'),
styl:generateLoaders('stylus')
}
}
// 生成开发环境下的loader的配置,使用在(webpack.dev.config.js中)
exports.styleLoaders = function(options){
const output = []
// 调用cssLoader方法 返回loaders的对象
const loaders = exports.cssLoaders(options)
// 遍历每一个loader 并配置成对应的格式 传给output数组
for(const extension in loaders){
const loader = loaders[extension]
output.push({
test:new RegExp('\\.'+extension + '$'),
use:loader
})
}
return output
}
vue-loader.config
'use strict'
// 引入上面的utils文件
const utils = require('./utils')
// 引入config文件
const config = require('./config')
// 判断当前是否为生产环境,如果是则返回true
const isProdction = progress.env.NODE_ENV === 'prodction'
// 是否使用sourceMap如果是生产环境就使用config文件中的index.js中的生产环境配置,否则是否开发环境的配置
const sourceMapEnabled = isProdction ? config.build.productionSourceMap:config.dev.cssSourceMap
module.exports = {
//utils文件cssLoaders返回的配置项,返回的格式为
// loaders:{
// css:ExtractTextPlugin.extract({
// use:[cssLoader],
// extract默认行为先使用css-loader编译css,如果一切顺利的话,结束之后把css导出到规定的文件去。但是如果编译过程中出现了错误,则继续使用vue-style-loader处理css。
// fallback:'vue-style-loader'
// }),
// postCss:{
// ...
// }
// }
loaders:utils.cssLoaders({
sourceMap:sourceMapEnabled,
extract:isProdction
}),
// 是否使用sourceMap
cssSourceMap:sourceMapEnabled,
// 是否使用cacheBusting,这个配置在config的文件
cacheBusting:config.dev.cacheBusting
}
webpack.base.config.js
/*
* @Author: yang
* @Date: 2020-10-16 13:48:48
* @LastEditors: yang
* @LastEditTime: 2020-10-17 14:43:50
* @FilePath: \新建文件夹 (4)\webpack.base.config.js
*/
const path = require('./path')
const utils = require('./utils')
const config = require('./config')
const vueLoaderConfig = require('./vue-loader.config')
// resolve函数返回根路径下的文件或文件夹
function resolve(dir){
return path.join(__dirname,'..',dir)
}
module.exports = {
// 返回根路径
context:path.resolve(__dirname,'../'),
// 设置入口文件
entry:{
app:'./src/main.js'
},
// 设置出口文件
output:{
//根据config模块得知是根目录下的dist文件夹
path:config.build.assetsRoot,
filename:'[name].js',
//公共路径统一为'/'
publicPath:ProgressEvent.env.NODE_ENV === 'prodution'?config.build.assetsPublicPath:config.dev.assetsPublicPath
},
resolve:{
//自动解析的扩展,js vue ,json这三种格式得文件引用时不需要加上扩展了
//import File from '../path/fo/file'
extensions:['.js','.vue','.json'],
alias:{
// 精准匹配,使用vue来替代vue/dist/vue.esm.js路径
'vue$':'vue/dist/vue.esm.js',
'@':resolve('src')
}
},
module:{
rules:[
//vue-loader,module
{
test: /\.vue$/,
loader:'vue-loader',
options:vueLoaderConfig
},
{
test:/\.js$/,
loader:'babel-loader',
// 把要处理的目录包括进来
include:[resolve('src'),resolve('test'),resolve('node_modules/webpack-dev-server/client')]
},
{
test:/\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
loader:'url-loader',
options:{
limit:10000,//超过10kb的才使用url-loader来映射到文件
name:utils.assetsPath('media/[name].[hash:7].[ext]')//其他的资源转移到静态资源文件夹
}
},
{
test:/\.(woff2?|eot|ttf|otf)(\?.*)?$/,
loader:'url-loader',
options:{
limit:10000,
name:utils.assetsPublicPath('fonts/[name].[hash:7].[text]')
}
}
]
}
}
webpack.dev.conf.js
/*
* @Author: yang
* @Date: 2020-10-17 16:16:57
* @LastEditors: yang
* @LastEditTime: 2020-10-18 14:24:04
* @FilePath: \新建文件夹 (4)\webpack.dev.conf.js
*/
const utils = require('./utils')
const webpack = require('webpack')
const config = require('./config')
const merge = require('webpack-merge')
const path = require('path')
const baseWebpackConfig = require('./webpack.base.config')
// 拷贝资源的插件
const CopyWebapckPlugin = require('copy-webpack-plugin')
// 生成html模板的插件
const HtmlWebpackPlugin = require('html-webpack-plugin')
// 展示错误日志的插件
const FriendlyErrorsPlugin = require('frendly-errors-webpack-plugin')
// 一个自动打开可用端口的包
const portfinder = require('portfinder')
// 当前环境的host
const HOST = progress.env.HOST
//当前环境的port
const PORT = progress.env.PORT&&Number(progress.env.PORT)
// 开发环境的配置
const devWebpackConfig = merge(baseWebpackConfig,{
module:{
//loader的配置
rules:utils.styleLoaders({
sourceMap:config.dev.cssSourceMap,usePostCSS:true
}),
devtool:config.dev.devtool,
devServer:{
// 重新加载server时,控制台对一些错误以warning的方式提示
clientLogLevel:'warning',
//当使用HTML5 history API时 任意的404响应都可能需要被替代为index.html
historyApiFallback:{
rewrites:[
{from:/.*/,to:path.posix.join(config.dev.assetsSubDirectory,'index.html')}
]
},
// 启用webpack的模块热替换特性
hot:true,
//告诉服务器从哪里提供内容。只有在你想要提供静态文件是才需要
contentBase:false,
// 是否压缩
compress:false,
host:HOST||config.dev.host,
port:PORT||config.dev.port,
// 是否自动打开浏览器
open:config.dev.autoOpenBrowser,
// 编译出错时是否有提示
overlay:config.dev.errorOverlay?{warning:false,errors:true}:false,
//静态内容的路径,此路径下的打包文件可在浏览器中访问
publicPath:config.dev.assetsPublicPath,
//接口的代理
proxy:config.dev.proxyTable,
// 启用quiet后,除了初始启动信息外的任务内容都不会被打印到控制台。这也意味着来自webpack的错误或警告在控制台不可见
quite:true,
// 监视文件的选项
watchOptions:{
poll:config.dev.poll
}
},
plugins:[
// DefinePlugin允许创建一个在编译时可以配置的全局常量。这里生成了一个当前环境的常量
new webpack.DefinePlugin({
'progress.env':require('../config/dev.env')
}),
//模块热替换插件 修改模块是不需要刷新页面
new webpack.HotModuleReplacementPlugin(),
//当开启HMR的时候使用该插件会显示模块的相对路径
new webpack.NamedModulesPlugin(),
// 在编译出现错误时,使用NoEmitOnErrorsPlugin来跳过输出阶段 这样可以确保输出资源不会包含错误
new webpack.NoEmitOnErrorsPlugin(),
new HtmlWebpackPlugin({
filename:'index.html',
template:'index.html',
// 打包后js文件放在body的后面
inject:true
}),
//将static的内容拷贝到开发路径,忽略这个文件夹下的'.XX'的文件
new CopyWebapckPlugin([
{
from:path.resolve(__dirname,'../static'),
to:config.dev.assetsSubDirectory,
ignore:['.*']
}
])
]
}
})
webpack.prod.conf.js
/*
* @Author: yang
* @Date: 2020-10-17 14:45:20
* @LastEditors: yang
* @LastEditTime: 2020-10-17 16:15:15
* @FilePath: \新建文件夹 (4)\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.config')
// 资源拷贝的插件
const CopyWebpackPlugin = require('copy-webpack-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')
// 把css打包成css文件已link的方式引入包
const ExtractTextPlugin = require('extract-text-webpack-plugin')
// 压缩css的包
const OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin')
// 压缩js代码的包
const UglifyJsPlugin = require('uglifyjs-webpack-plugin')
const env = require('./config/prod.env')
const webpackConfig = merge(baseWebpackConfig,{
module:{
//loader配置,可在介绍utils的文章中查看
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:config.build.assetsPath('js/[name].[chunkhash].js'),
//chunkFilename用于命名那些异步加载的模块,比如通过require.ensure()
chunkFilename:utils.assetsPath('js/[id].[chunkhash].js')
},
plugins:[
new webpack.DefinePlugin({
'progress.env':env
}),
//压缩js代码
new UglifyJsPlugin({
uglifyOptions:{
compress:{
warnings:false
}
},
sourceMap:config.build.productionSourceMap,
parallel:true
}),
// 从所有额外的chunk(additional chunk)提取(默认情况下,它仅从初Zchunk(init chunk)中提取)
// 当使用CommonsChunkPlugin 并且在公共chunk中提取的chunk(来自ExtractText)时 allChunks **必须设置为true
new ExtractTextPlugin({
filename:utils.assetsPath('css/[name].[contenthash].css'),
allChunks:true,
}),
//压缩css
//优化最小化css代码 如果只简单使用extract-text-plugin可能会造成css重复
new OptimizeCSSPlugin({
cssProgressorOptions:config.build.productionSourceMap?
{safe:true,map:{inline:false}}:{safe:true}
}),
//在dist目录生成html文件
//将产品文件的引用注入到index.html
new HtmlWebpackPlugin({
filename:config.build.index,
template:'index.html',
inject:true,
minify:{
// 删除index.html中的注释
removeComments:true,
// 删除index.html中的空格
collapseWhitespace:true,
//删除各种html标签属性值的双引号
removeAttributeQuotes:true,
},
// 注入依赖的时候按照依赖先后顺序进行注入,比如 需要先注入vendor.js,再注入app.js
chunksSortMode:"dependency"
}),
// 该插件会根据模块的相对路径生成一个四位数的hash作为模块id 建议用于生产环境
new webpack.HashedModuleIdsPlugin(),
// 去webpack打包时的一个取舍是将bundle中各个模块单独打包成闭包 这些打包函数使你的js在浏览器中处理的很慢,
//相比之下,一些工具 想Closure Compiler和RollupJS可以提升(hoist)或者预编译所有模块到一个闭包中,提升你的代码在浏览器中的执行速度
new webpack.optimize.ModuleConcatenationPlugin(),
// 将第三方的包分离出来 将所有从node-modules中引的js提取到vendor.js,即抽取文件
new webpack.optimize.CommonsChunkPlugin({
name:'vendor',
minChunks(module){
return(
module.resource&&/\.js$/.test(module.resource)&&module.resource.indexof(path.join(__dirname,'../node_modules'))===0
)
}
}),
// 为了避免每次更改项目代码时导致venderchunk的chunkHash改变,我们还会单独生成一个manifestchunk
new webpack.optimize.CommonsChunkPlugin({
name:'manifest',
minChunks:Infinity
}),
// 我们主要逻辑的js文件
new webpack.optimize.CommonsChunkPlugin({
name:'app',
async:'vendor-async',
children:true,
minChunks:3
}),
// 拷贝资源 将static文件夹里面的静态资源复制到dist/static
new CopyWebpackPlugin([
{
from:path.resolve(__dirname,'../static'),
to:config.build.assetsSubDirectory,
ignore:['.*']
}
])
]
})
module.exports = webpackConfig
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。