webpack 的链式配置

6,699 阅读3分钟

API参考http://npm.taobao.org/package/webpack-chain
使用链式调用 1、代码更加简洁
2、维护性强
3、编程性强
4、对程序员的业务能力要求高

webpack-chain 简介

链式包装器 引入 webpack-chain 后,我们所有的 webpack 配置通过一个链式包装器便可生成了:

const Config = require('webpack-chain');
const config = new Config();
// 链式生成配置
...
// 导出 webpack 配置对象
export default config.toConfig();

安装webpack-chain

npm install webpack-chain -D 或者 yarn add webpack-chain -D

分离配置文件

目录结构

1、新建文件夹build 新建webpack.base.conf.js(webpack基本配置文件)

/**
 * @file webpack基本配置文件
 */
'use strict'
const path = require('path')
const Config = require('webpack-chain') 
const CopyWebpackPlugin = require('copy-webpack-plugin')
const webpackConfig = new Config()
webpackConfig
    .mode(process.env.NODE_ENV)
    .target('web') //编译为类浏览器环境里可用
    .context(path.resolve(__dirname, '../'))
    .entry('app')
    .add(`./src/index.js`)
    .end()
webpackConfig.output
    .path(path.resolve(__dirname, "../dist"))
	.filename('[name].js')
	.end()
webpackConfig.resolve
    .set('symlinks', false) // 将符号链接(symlink)解析到它们的符号链接位置
    .extensions
        .merge(['.js', '.jsx', '.vue', '.json']) // 自动解析确定的扩展
    .end()
    .alias
        .set('@', path.join(__dirname, '..', 'src'))
        .set('vue$', utils.isDev() ? 'vue/dist/vue.esm.js' : 'vue/dist/vue.runtime.esm.js')
// resolveLoader-----------------
webpackConfig.resolveLoader.modules
   .add('node_modules')
   .add(path.join(__dirname, './loaders'))
//react处理js配置
webpackConfi.module
    .rule('compile')
	.test(/\.js$/)
	.pre()
	.include
	    .add(basePath)
	    .end()
	.use('babel')
	    .loader('babel-loader?cacheDirectory=true')
    	.options({
    		presets: ['es2015', 'react', 'stage-1','babel-polyfill']
    	})
    	.end()
	.use('react-hot-loader/webpack')
    	.loader('react-hot-loader/webpack')
    	.end()
  	.end()
//处理vue文件
webpackConfig.module
  .rule('vue')
    .test(/\.vue$/)
    .use('vue-loader')
      .loader('vue-loader')
      .options({
        compilerOptions: {
          preserveWhitespace: false
        }
      })
      .end()
// 静态资源配置 --------------------
webpackConfig.module
  .rule('images')
    .test(/\.(png|jpe?g|gif|webp)(\?.*)?$/)
    .use('url-loader')
      .loader('url-loader')
      .options({
        limit: 5000,
        name: utils.assetsPath('img/[name].[hash:7].[ext]')
      })
/ svg 不用内联方式
// see https://github.com/facebook/create-react-app/pull/1180
webpackConfig.module
  .rule('svg')
    .test(/\.(svg)(\?.*)?$/)
    .use('file-loader')
      .loader('file-loader')
      .options({
        name: utils.assetsPath('img/[name].[hash:7].[ext]')
      })
webpackConfig.module
  .rule('fonts')
    .test(/\.(woff2?|eot|ttf|otf)(\?.*)?$/i)
    .use('url-loader')
      .loader('url-loader')
      .options(genUrlLoaderOptions('fonts'))
//css文件配置,我这用的是sass
webpackConfig.module
.rule('scss')
    	.test(/\.scss$/)
    	.use('css-hot-loader')
    		.loader('css-hot-loader')
    		.end()
    	.use('mini-css-extract-loader')
    		.loader(devMode ? MiniCssExtractPlugin.loader : 'style-loader')
    		.end()
    	.use('css-loader')
    		.loader('css-loader')
    		.options({
    			importLoaders: 2
    		})
    		.end()
    	.use('postcss-loader')
    		.loader('postcss-loader')
    		.end()
    	.use('sass-loader')
    		.loader('sass-loader')
    		.end()
    	.end()
//  插件-------------------------
// 导出html
webpackConfig
  .plugin('html')
    .use(require('html-webpack-plugin'), [{
      filename: 'index.html',
      template: './src/index.html',
      inject: true
    }])
// 复制静态资源
webpackConfig
  .plugin('copy-static')
  .use(CopyWebpackPlugin, [[
    { from: path.join(__dirname, '../', 'static'), to: config.meshProp('outputRoot') }
  ]])
// 打包前清除输出目录
if (!utils.isDev()) {
  webpackConfig
    .plugin('clean')
    .use(require('clean-webpack-plugin'))
}
//多线程
webpackConfig
    .plugin('HappyPack')
    .use(HappyPack,[{
    	//用id来标识 happypack处理那里类文件
    	id: 'happyBabel',
    	//如何处理  用法和loader 的配置一样
    	loaders: [{
    		loader: 'babel-loader?cacheDirectory=true',
    	}],
    	//共享进程池threadPool: HappyThreadPool 代表共享进程池,即多个 HappyPack 实例都使用同一个共享进程池中的子进程去处理任务,以防止资源占用过多。
    	threadPool: happyThreadPool,
    	//允许 HappyPack 输出日志
    	verbose: true,
    }])
//把css提取成单独的css文件
webpackConfig
    .plugin('MiniCssExtractPlugin')
    .use(MiniCssExtractPlugin, [{
    	filename: devMode ? 'css/[name].[hash].css' : 'css/[name].css',
    	chunkFilename: devMode ? 'css/[name].[hash].css' : 'css/[name].css'
    }])
module.exports = config.toConfig();

2、webpack.dev.conf.js(webpack基本配置文件)

/**
 * @file 开发环境webpack配置文件
 */
'use strict'
const path = require('path')
const webpackConfig = require('./webpack.base.conf')
// 获取本地IP
function getLocalIP () {
  let interfaces = os.networkInterfaces()
  for(let devName in interfaces){
    let iface = interfaces[devName]
    for(let i=0;i<iface.length;i++){
      let alias = iface[i];
      if(alias.family === 'IPv4' && alias.address !== '127.0.0.1' && !alias.internal){
        return alias.address;
      }
    }
  }
  return 'localhost'
}
webpackConfig
  .mode('development')
webpackConfig.devtool('cheap-module-eval-soure-map')
webpackConfig
  .devServer
    .hot(true) // 是否支持热替换【热替换有问题,先置为false,保证可以自动刷新页面】
    // .inline(true)
    .contentBase(path.resolve(__dirname, "../dist"))
    .watchContentBase(true)
    .host(getLocalIP)
    .port(8080)
    .compress(false)
    .open(true) // 是否自动打开浏览器
    .overlay({warnings: false, errors: true}) //页面是否增加遮罩层显示错误信息
webpackConfig.watch(true)
webpackConfig.watchOptions({
	aggregateTimeout: 500, //防止重复保存频繁重新编译,500毫秒内重复保存不打包
	poll: 1000, //每秒询问的文件变更的次数
	ignored: /node_modules/ //忽略不需要坚挺的目录
})
webpackConfig.plugin('HotModuleReplacementPlugin')
  .use(webpack.HotModuleReplacementPlugin)
//console.log('>>>>>>>>>>>>>\n', config.toString())
//可以打印出来看看配置的文件格式是什么样子的
module.exports = merge(commonConfig,config.toConfig())

2、webpack.pro.conf.js(webpack基本配置文件)

/**
 * @file 生产环境webpack配置文件
 */
'use strict'
const webpackConfig = require('./webpack.base.conf')
const merge = require('webpack-merge')

const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;//打印出来文件的大小分布情况
webpackConfig.mode('production')
webpackConfig.mode('production')
webpackConfig.entry('pollify')
  .add('babel-polyfill')
webpackConfig.devtool('cheap-module-source-map')
const splitConfig = {
  vendors: {
    name: `vendors`,
    minChunks: 2,
    test: /[\\/]node_modules[\\/]/,
    priority: -10,
    chunks: 'initial'
  },
  common: {
    name: 'common',
    minChunks: commonMinChunks,
    priority: -20,
    chunks: 'initial',
    reuseExistingChunk: true
  },
  async: {
    name: 'async-common',
    minChunks: 2,
    maxAsyncRequests: 3,
    priority: -30,
    chunks: 'async',
    reuseExistingChunk: true
  }
}
webpackConfig
  .optimization.splitChunks({ name: false, cacheGroups: splitConfig })
webpackConfig.optimization
  .minimizer('css')
  .use(OptimizeCSSAssetsPlugin, [{ cssProcessorOptions: { safe: true }}]) //压缩css
module.exports = merge(commonConfig, config.toConfig())

总结:大家不妨试试webpack的链式调用,相信大家会发现它的独特之处,鄙人初来乍到,如有错误之处,还请指出,希望能帮到您