vue中webpack配置介绍

在my-project项目中的build文件夹下我们看到了这四个文件:


image.png

下面我们一个一个剖析:

webpack.base.conf.js 主要对build目录下的webpack配置做详细分析

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

module.exports = {
    //入口
  entry: {
    app: './src/main.js'
  },
  //输出
  output: {
    path: config.build.assetsRoot,//导出目录的绝对路径
    filename: '[name].js',//导出文件的文件名
    publicPath: process.env.NODE_ENV === 'production'
      ? config.build.assetsPublicPath
      : config.dev.assetsPublicPath//生产模式或开发模式下html、js等文件内部引用的公共路径
  },
  //文件解析
  resolve: {
    extensions: ['.js', '.vue', '.json'],//自动解析确定的拓展名,使导入模块时不带拓展名
    alias: {// 创建import或require的别名
//       'vue': 'vue/dist/vue.js',
      'vue$': 'vue/dist/vue.esm.js',
      '@': resolve('src'),
    }
  },
  //模块解析
  module: {
    rules: [
      {
        test: /\.(js|vue)$/,//js和vue文件后缀
        loader: 'eslint-loader',//使用eslint-loader处理
        enforce: 'pre',//
        include: [resolve('src'), resolve('test')],//
        options: {
          formatter: require('eslint-friendly-formatter')
        }//对eslint-loader做的额外处理
      },
      {
        test: /\.vue$/,//vue文件后缀
        loader: 'vue-loader',//使用vue-loader处理
        options: vueLoaderConfig//对vueloader的一些额外处理
      },
      {
        test: /\.js$/,//js文件后缀
        loader: 'babel-loader',//使用babel-loader处理
        include: [resolve('src'), resolve('test')]//必须包含src和test文件夹
      },
      {
        test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,//图片后缀
        loader: 'url-loader',//使用url-loader处理
        options: { //对loader做的额外的选项配置
          limit: 10000,//图片小于10000字节,以base64方式引用
          name: utils.assetsPath('img/[name].[hash:7].[ext]')//文件名是name.7位hash值.拓展名
        }
      },
      {
        test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,//媒体文件
        loader: 'url-loader',//媒体文件使用url-loader来处理
        options: {//对loader做的额外的选项配置
          limit: 10000,//媒体文件小于10000字节,以base64方式引用
          name: utils.assetsPath('media/[name].[hash:7].[ext]')//文件名是name.7位hash值.拓展名
        }
      },
      {
        test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,//字体文件
        loader: 'url-loader',//使用url-loader来处理
        options: {//对字体文件的loader做的额外的选项配置
          limit: 10000,//字体文件小于10000字节,以base64方式引用
          name: utils.assetsPath('fonts/[name].[hash:7].[ext]')//文件名是name.7位hash值.拓展名
        }
      }
    ]
  }
}
//注: 关于query 仅由于兼容性原因而存在。请使用 options 代替。

webpack.dev.conf.js 开发环境下的webpack配置,通过merge方法合并webpack.base.conf.js基础配置

'use strict'
const utils = require('./utils')
const webpack = require('webpack')
const config = require('../config')
const merge = require('webpack-merge')
const baseWebpackConfig = require('./webpack.base.conf')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin')

// add hot-reload related code to entry chunks
Object.keys(baseWebpackConfig.entry).forEach(function (name) {
  baseWebpackConfig.entry[name] = ['./build/dev-client'].concat(baseWebpackConfig.entry[name])
})

module.exports = merge(baseWebpackConfig, {
    //模块配置
  module: {
    //通过传入一些配置来获取rules配置,此处传入了sourceMap: false,表示不生成sourceMap
    rules: utils.styleLoaders({ sourceMap: config.dev.cssSourceMap })
  },
  // cheap-module-eval-source-map is faster for development
  devtool: '#cheap-module-eval-source-map',
  //插件配置
  plugins: [
    new webpack.DefinePlugin({// 编译时配置的全局变量
      'process.env': config.dev.env//当前环境为开发环境
    }),
    // https://github.com/glenjamin/webpack-hot-middleware#installation--usage
    new webpack.HotModuleReplacementPlugin(),//热更新插件
    new webpack.NoEmitOnErrorsPlugin(),//不触发错误,即编译后运行的包正常运行
    // https://github.com/ampedandwired/html-webpack-plugin
    new HtmlWebpackPlugin({//自动生成html文件,比如编译后文件的引入
      filename: 'index.html',//生成的文件名
      template: 'index.html',//模板
      inject: true
    }),
    new FriendlyErrorsPlugin()//友好的错误提示
  ]
})

webpack.prod.conf.js 生产环境下的webpack配置,通过merge方法合并webpack.base.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 env = process.env.NODE_ENV === 'testing'
  ? require('../config/test.env')
  : config.build.env

const webpackConfig = merge(baseWebpackConfig, {
    //module的处理,主要是针对css的处理
  module: {
    rules: utils.styleLoaders({
      sourceMap: config.build.productionSourceMap,
      extract: true
    })
  },
  devtool: config.build.productionSourceMap ? '#source-map' : 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//配置全局环境为生产环境
    }),
    // UglifyJs do not support ES6+, you can also use babel-minify for better treeshaking: https://github.com/babel/minify
    new webpack.optimize.UglifyJsPlugin({//js文件压缩插件
      compress: {//压缩配置
        warnings: false//不显示警告
      },
      sourceMap: true//生成sourceMap文件
    }),
    // extract css into its own file
    new ExtractTextPlugin({//将js中引入的CSS分离的插件
      filename: utils.assetsPath('css/[name].[contenthash].css')//分离出的CSS文件名
    }),
    // Compress extracted CSS. We are using this plugin so that possible
    // duplicated CSS from different components can be deduped.
    //压缩提取的CSS,并解决ExtractTextPlugin分离出的js重复的问题(多个文件引入同一CSS文件)
    new OptimizeCSSPlugin({
      cssProcessorOptions: {
        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
    //生成HTML文件的插件,引入CSS文件和js文件
    new HtmlWebpackPlugin({
      filename: process.env.NODE_ENV === 'testing'
        ? 'index.html'
        : config.build.index,//生成的HTML文件名
      template: 'index.html',//依据的模板
      inject: true,//注入的js文件将会被放在body标签中,当值为head时将会被放在head标签中
      minify: {//压缩配置
        removeComments: true,//删除HTML中的注释代码
        collapseWhitespace: true,//删除HTML中的空白字符
        removeAttributeQuotes: true//删除HTML元素中属性的引号
        // more options:
        // https://github.com/kangax/html-minifier#options-quick-reference
      },
      // necessary to consistently work with multiple chunks via CommonsChunkPlugin
      chunksSortMode: 'dependency'//按照dependency的顺序引入
    }),
    // keep module.id stable when vender modules does not change  保持模块。当vender模块没有改变时,id就稳定了
    new webpack.HashedModuleIdsPlugin(),
    // split vendor js into its own file  将供应商js分解为自己的文件
    //分离公共js到vendor中
    new webpack.optimize.CommonsChunkPlugin({
      name: 'vendor',//文件名
      minChunks: function (module) {//申明公共的模块来自node_modules中
        // 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
    //将webpack运行时和模块清单提取到自己的文件中,以防止当应用程序包被更新时,供应商哈希被更新。
    //上面虽然已经分离了第三方库,每次修改编译都会改变vendor的hash值,导致浏览器缓存失效。
        //原因是vendor包含了webpack在打包过程中会产生一些运行时代码,运行时代码中实际上保存了打包后的文件名。
        //当修改业务代码时,业务代码的js文件的hash值必然会改变。一旦改变必然会导致vendor变化。vendor变化会导致其hash值变化。
    //下面主要是将运行时代码提取到单独的manifest文件中,防止其影响vendor.js
    new webpack.optimize.CommonsChunkPlugin({
      name: 'manifest',
      chunks: ['vendor']
    }),
    // copy custom static assets
     // 复制静态资源,将static文件内的内容复制到指定文件夹
    new CopyWebpackPlugin([
      {
        from: path.resolve(__dirname, '../static'),
        to: config.build.assetsSubDirectory,
        ignore: ['.*']//忽略*文件
      }
    ])
  ]
})
//额外配置
if (config.build.productionGzip) {//配置文件开启了gzip压缩
    //引入压缩文件的组件,该插件会对生成的文件进行压缩,生成一个.gz文件
  const CompressionWebpackPlugin = require('compression-webpack-plugin')

  webpackConfig.plugins.push(
    new CompressionWebpackPlugin({
      asset: '[path].gz[query]',//目标文件名
      algorithm: 'gzip',//使用gzip压缩
      test: new RegExp(//满足正则表达式的文件会被压缩
        '\\.(' +
        config.build.productionGzipExtensions.join('|') +
        ')$'
      ),
      threshold: 10240,//资源文件大于10240B = 10KB大小才会被压缩
      minRatio: 0.8//最小压缩比达到0.8时才会被压缩
    })
  )
}

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

module.exports = webpackConfig

webpack.test.conf.js

'use strict'
// This is the webpack config used for unit tests.
//这是用于单元测试的webpack配置。
const utils = require('./utils')
const webpack = require('webpack')
const merge = require('webpack-merge')
const baseWebpackConfig = require('./webpack.base.conf')

const webpackConfig = merge(baseWebpackConfig, {
  // use inline sourcemap for karma-sourcemap-loader
//为karma-sourcemap加载器使用内联sourcemap
  module: {
    rules: utils.styleLoaders()
  },
  devtool: '#inline-source-map',
  resolveLoader: {
    alias: {
      // necessary to to make lang="scss" work in test when using vue-loader's ?inject option
      // see discussion at https://github.com/vuejs/vue-loader/issues/724
//  在使用vuloader的时候,需要使lang=“scss”在测试中工作吗?请参阅[https://github.com/vuejs/vue-loader/issues/724]的讨论注入选项
      'scss-loader': 'sass-loader'
    }
  },
  plugins: [
    new webpack.DefinePlugin({
      'process.env': require('../config/test.env')
    })
  ]
})

// no need for app entry during tests
//在测试中不需要应用程序条目
delete webpackConfig.entry

module.exports = webpackConfig
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 196,264评论 5 462
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 82,549评论 2 373
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 143,389评论 0 325
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,616评论 1 267
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,461评论 5 358
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,351评论 1 273
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,776评论 3 387
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,414评论 0 255
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,722评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,760评论 2 314
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,537评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,381评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,787评论 3 300
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,030评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,304评论 1 252
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,734评论 2 342
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,943评论 2 336

推荐阅读更多精彩内容