webpack 常用配置及插件

更新 webpack4 的部分配置

  • 问题
    1、不能再使用 extract-text-webpack-plugin提取 css 文件,而是用 mini-css-extract-plugin

2、production 模式下 optimization 的配置中,要加上 concatenateModules: false, 否则打出的包会有问题,这似乎是 webpack 的bug

  • 新配置 optimization 中的 SplitChunksPlugin
    SplitChunksPlugin 提供了两种控制 chunk 抽取模块范围的方式:

第一种是 test 属性。这个属性可以传入字符串、正则或者函数,所有的 module 都会去匹配 test 传入的条件,如果条件符合,就被纳入这个 chunk 的备选模块范围。

vendor: {
  test: /[\\/]node_modules[\\/]/,
  name: 'vendor',
  chunks: 'all'
}

第二种方式是 chunks 属性。chunks 可以是字符串,比如 'all'|'async'|'initial',分别代表了全部 chunk,按需加载的 chunk 以及初始加载的 chunk。chunks 也可以是一个函数,在这个函数里我们可以拿到 chunk.name。
// 有 a, b, c 三个入口,我们希望 a,b 的公共代码单独打包为 common

optimization: {
  splitChunks: {
    cacheGroups: {
      common: {
        chunks(chunk) {
          return chunk.name !== 'c'
        }
        name: 'common',
        minChunks: 2
      }
    }
  }
}

以下为原文:
本文记录webpack2中的常用配置项和插件

1、常用配置

 module.exports = {
  cache: true,  //开启缓存功能,这样只有变化的文件才会重新加载,可提升构建速度
  entry:{},
  output: {},
  module: {},
  resolve: {},
  externals:{},
  plugins:{}
}

1.1 entry

  • 单入口时key为app,value写上相对于webpack.config.js的入口文件路径即可,如:


    单入口

    注意:value还可以是数组,这种情况要注意顺序,确保主入口在数组的末位上!

  • 多入口时key为app的是主入口,其他key可自己取名,但要加引号,如:


    多入口

    注意:有几个入口,webpack就会打几个包(bundle)出来,打出来的包的文件名与这里的key对应,比如上图会打出类似app.js和vendor.js两个文件(这里省略了hash)。

1.2 output

  • path
    规定打包后的文件放哪儿,必须是绝对路径,常取值为:
    __dirname+’/build’或path.resolve(__dirname,’build’)
  • filename
    规定打包后的文件的名字,对于单入口文件,可以取一个固定的名字,如’build.js’,对于多入口文件,要使用[name].bundle.js或[id].bundle.js来对应,其中name和id是根据多入口文件对象的属性动态确定的
  • publicPath
    规定线上地址,打包后的文件中资源的引用地址会根据这个地址而改变,一般取为’/assets/’
  • chunkFilename
    webpack可以做代码分割,这个属性规定那些做了代码分割的块(chunk)的名字
    默认使用 [id].js
    webpack中的path、publicPath、contentBase的区分

1.3 module

  • rules:数组
    数组中每一项类似于这样配置:
     {
        test: /\.js$/,
        loader: 'babel-loader?cacheDirectory=true', //当使用多个loader时,请用use而不是loaders代替loader
        include: [resolve('src'), resolve('test')],
        exclude: [resolve('node_modules')]
      }

有时还会有query或options配置,二者都是use:{options}的简写,所以在用了use后就不需要这两个配置了,如下(一个loader对应一个options,使用多个loader时用use):

use: [
  {
    loader: 'style-loader'
  },
  {
    loader: 'css-loader',
    options: {
      importLoaders: 1
    }
  },
  {
    loader: 'less-loader',
    options: {
      noIeCompat: true
    }
  }
]
  • noParser
    防止 webpack 解析任何与给定正则表达式相匹配的文件,忽略大型库文件(library)可以提高构建性能
noParse: /jquery|lodash/

1.4 resolve

配置模块如何解析

  • root:字符串或值为字符串的数组,绝对路径,配置alias中依赖项的基地址
  • alias
    创建 import 或 require 的别名,来确保模块引入变得更简单。
    对象,key为变量名,值为路径。key指定的变量将成为全局变量,比如想在任何文件中都是用jquery而不必每次都显示引入,可以这样{$:jquery文件的地址},地址可以是相对地址(相对root指定),也可是绝对地址(使用path.resolve(__dirname,’jquery’)).
  • extensions:数组,文件扩展名,某文件的扩展名在该数组中时,该文件在引入时可省略扩展名,常取值有[‘’ , ’.js’ , ‘.json’ , ‘.scss’ , ‘.vue’]
  • modules
    告诉 webpack 解析模块时应该搜索的目录
resolve: {
    extensions: ['.js', '.vue', '.json'],
    modules: [
      resolve('src'),     //实际返回了src的路径,会优先于node_modules搜索
      resolve('node_modules')
    ],
    alias: {
      'vue$': 'vue/dist/vue.common.js',
      'src': resolve('src'),
      'assets': resolve('src/assets'),
      'components': resolve('src/components'),
      'styles': resolve('src/styles'),
      'utils':resolve('src/utils'),
      'demos':resolve('src/demos'),
      'cnode':resolve('src/cnode')
    }
  }

1.5 externals

提供了不从 bundle 中引用依赖的方式。也就是所创建的 bundle 依赖于那些存在于用户环境(consumer environment)中的依赖。比如jquery是用script的方式从html引入的,要想在其他模块中引入的时候就可以使用这个配置

// html

// 配置
externals: {
  $: 'jQuery'            //key不加引号,value是脚本里的全局对象,这里value还可以是数组或对象,但表示的含义大不一样,可参看[这里](http://www.css88.com/doc/webpack2/configuration/externals/)
}
// 其他模块引入的方式
import $ from 'jquery';

1.6 performance、stat

performance:某个打包后的包超过给定阈值时给出提示
stat:控制webpack打包后输出哪些信息

1.7 plugins

plugins是除module外最为重要的配置了,插件机制提供了loader无法完成的功能,常用的plugin有:

  • CommonsChunkPlugin
  • DefinePlugin
  • HtmlWebpackPlugin
  • UglifyjsWebpackPlugin
  • ExtractTextWebpackPlugin
  • OptimizeCSSPlugin
  • CompressionWebpackPlugin
  • SourceMapDevToolPlugin
  • FriendlyErrorsPlugin
  • BundleAnalyzerPlugin

2、插件用法配置

  • CommonsChunkPlugin
new webpack.optimize.CommonsChunkPlugin(options)

options的配置:
name:抽取出公共代码后的模块名,若没有filename项,该项也决定打包后的文件名
chunks:从哪些模块中抽取公共代码,若省略,则从所有模块中抽取(一般是从入口模块抽)
minChunks:number|Infinity|function(module, count) -> boolean
为数字A时,表示模块必须被引用超过A次才提取到公共代码里;为infinity时,表示无穷,不抽取任何模块;为函数时,函数返回true就抽取,实例:

                new webpack.optimize.CommonsChunkPlugin({
            name: 'vendor',
            minChunks: function(module, count) {
                // 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
                )
            }
        })
  • DefinePlugin
    允许你创建一个在编译时可以配置的全局常量。
                new webpack.DefinePlugin({
            'process.env': config.dev.env
        })

注意这里定义的常量是在业务模块中使用的,并不是在webpack这些配置文件中使用,因为webpack本身运行在node环境下,node中自身就有process等全局变量。如在入口main.js中不用声明process.env就可以直接使用process.env判断环境

  • HtmlWebpackPlugin
    生成一个HTML5文件,该文件的 body 中使用script 标记引用了所有 webpack bundle。若有多个webpack入口点,它们都将包含在生成的HTML中,使用script标记引用。如果有任何CSS资源在webpack的 output 中,(例如,使用ExtractTextPlugin提取的CSS)那么这些资源将被包含在HTML head 中,使用 标记引用。实例:
var HtmlWebpackPlugin = require('html-webpack-plugin');
var webpackConfig = {
  entry: 'index.js',
  output: {
    path: 'dist',
    filename: 'index_bundle.js'
  },
  plugins: [new HtmlWebpackPlugin()]
};

//生成一个文件 dist/index.html


  
    
    webpack App
  
  
    
  

配置:

  • title: 生成的html中的title
  • filename: 生成的html的名字
  • template: 用哪个模板来生成html
  • inject:true | 'head' | 'body' | false 取true或body时,all javascript 放在body底部,'head'放head里
  • favicon:指定生成的html的favicon
  • minify:{...} | false 压缩生成的html
  • hash: true | false 是否给所有scripts和css添加hash
  • cache: 只有当html中内容变化了才重新输出,默认true
  • showErrors:true | false 错误细节是否写到html,默认true
  • chunks: 只添加哪些chunk
  • excludeChunks: 去掉哪些chunk
  • UglifyjsWebpackPlugin
new webpack.optimize.UglifyJsPlugin({
       compress: {
         warnings: false
       },
       sourceMap: true
      })
// 或使用这个代替
var ParallelUglifyPlugin = require('webpack-parallel-uglify-plugin')
new ParallelUglifyPlugin({
      cacheDir: '.cache/',
      uglifyJS: {
        output: {
          comments: false,
          beautify: false
        },
        compress: {
          warnings: false,
          drop_console: true
        }
      }
    }),

配置项和uglify一样的

  • ExtractTextWebpackPlugin
    将所有的 入口chunk (entry chunks) 中的 require("style.css") 或import 'style.css' 移动到分开的 css 文件.
    需要两步:1、rules中配置 ExtractTextPlugin.extract 2、plugins中配置new ExtractTextPlugin("styles.css")
const ExtractTextPlugin = require("extract-text-webpack-plugin");
rules: [
      {
        test: /\.css$/,
        use: ExtractTextPlugin.extract({
          fallback: "style-loader",
          use: "css-loader"
        })
      }
    ]
  },
  plugins: [
    new ExtractTextPlugin("styles.css"),
  ]
  • OptimizeCSSPlugin
    去除重复的CSS代码
var OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin');
// 配置
  plugins: [
    new OptimizeCSSPlugin()
  ]
  • CompressionWebpackPlugin
    压缩资源
var CompressionPlugin = require("compression-webpack-plugin");
// 配置
 plugins: [
        new CompressionPlugin({
            asset: "[path].gz[query]",
            algorithm: "gzip",
            test: /\.js$|\.html$/,
            threshold: 10240,
            minRatio: 0.8
        })
    ]

asset: 目标资源名称。 [file] 会被替换成原始资源。[path] 会被替换成原始资源的路径, [query] 会被替换成查询字符串。默认值是 "[path].gz[query]"。
algorithm: 可以是 function(buf, callback) 或者字符串。对于字符串来说依照 zlib 的算法(或者 zopfli 的算法)。默认值是 "gzip"。
test: 所有匹配该正则的资源都会被处理。默认值是全部资源。
threshold: 只有大小大于该值的资源会被处理。单位是 bytes。默认值是 0。
minRatio: 只有压缩率小于这个值的资源才会被处理。默认值是 0.8。

  • BundleAnalyzerPlugin
    分析打包构成
var BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
  plugins: [
    new BundleAnalyzerPlugin({
  // Can be `server`, `static` or `disabled`.
  // In `server` mode analyzer will start HTTP server to show bundle report.
  // In `static` mode single HTML file with bundle report will be generated.
  // In `disabled` mode you can use this plugin to just generate Webpack Stats JSON file by setting `generateStatsFile` to `true`.
  analyzerMode: 'server',
  // Host that will be used in `server` mode to start HTTP server.
  analyzerHost: '127.0.0.1',
  // Port that will be used in `server` mode to start HTTP server.
  analyzerPort: 8888,
  // Path to bundle report file that will be generated in `static` mode.
  // Relative to bundles output directory.
  reportFilename: 'report.html',
  // Module sizes to show in report by default.
  // Should be one of `stat`, `parsed` or `gzip`.
  // See "Definitions" section for more information.
  defaultSizes: 'parsed',
  // Automatically open report in default browser
  openAnalyzer: true,
  // If `true`, Webpack Stats JSON file will be generated in bundles output directory
  generateStatsFile: false,
  // Name of Webpack Stats JSON file that will be generated if `generateStatsFile` is `true`.
  // Relative to bundles output directory.
  statsFilename: 'stats.json',
  // Options for `stats.toJson()` method.
  // For example you can exclude sources of your modules from stats file with `source: false` option.
  // See more options here: https://github.com/webpack/webpack/blob/webpack-1/lib/Stats.js#L21
  statsOptions: null,
  // Log level. Can be 'info', 'warn', 'error' or 'silent'.
  logLevel: 'info'
   })
  ]

3、webpack 配置热更新步骤

这里热更新是指局部重新加载,而非整个网页重新加载。

  • 开启webpack-dev-sever的hot:true
module.exports = {
  port: 3000,
  contentBase: './src',
  hot:true
}
  • 引入热加载插件 HotModuleReplacementPlugin
module.exports = [
  new webpack.DefinePlugin({
    'process.env.NODE_ENV': '"production"'
  }),
  new HtmlWebpackPlugin({
    template: resolve('src/index.html'),
    filename: resolve('dist/index.html')
  }),
  new webpack.HotModuleReplacementPlugin() // 热加载插件
]
  • 在入口文件接收热更新
ReactDOM.render(
  
    
  ,
  document.getElementById('root')
)

if (module.hot) {
  module.hot.accept()     // 这里不用写特定组件路径
}

4、webpack v4 的一些变化

参考

  • Vue项目Webpack优化实践,构建效率提高50%
  • 基于webpack4.X从零搭建React脚手架
  • [Webpack 4 不完全迁移指北 ](https://github.com/dwqs/blog/issues/60

你可能感兴趣的:(webpack 常用配置及插件)