阅读 110

关于webpack,你要知道的知识

webpack打包的原理:webpack都有entry、module、loader、chunk、output等配置选项。 webpack首先会根据entry找到对应所依赖的module(webpack会把所有的文件看多模块)进行递归解析,比如main.js、main.ts等等,同时也会根据loader对应的转换规则去转换,这些模块会以entry为单位进行分组,一个entry和其所有依赖的module被分到一个组,也就是一个chunk,最后webpack会把所有chunk转换成文件输出,在整个流程中webpack会在恰当的实际执行plugin定义的逻辑

多种配置类型
导出一个函数
module.exports = function(env,argv){
    return {
    mode: env.production? 'production': 'development'
    entry: './src/main.js',
    resolve: {
    },
    module: {
    rules: [
        {
              test: /\.json$/,
              use: 'json-loader'
          },
      ]
   },
  plugins: []
 }
}
复制代码
导出多个配置对象
module.exports = {
  context: path.resolve(__dirname, '../'),
  entry: {
    app: './src/main.js'
  },
  output: {
    path: config.build.assetsRoot,
    filename: '[name].js',
    publicPath: process.env.NODE_ENV === 'production' ? '/' : '/'
  },
  plugins: [],
  resolve: {
    alias: {
      '@': resolve('src'),
    }
  },
  module: {
   rules: [
    {
          test: /\.json$/,
          use: 'json-loader'
      },
  ]
}
复制代码
导出一个promise

webpack将运行有配置文件导出的函数,并且等到promise返回,便于需要一部加载所需的配置变量,貌似这种方式很少见。 我见的比较多是前两种方式

module.exports = () => {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve({
        entry: './app.js',
        /* ... */
      })
    }, 5000)
  })
}
复制代码
entry和context
context

Webpack 在寻找相对路径的文件时会以context 为根目录,context默认为执行启动 Webpack 时所在的当前工作目录。

context: path.resolve(__dirname, 'app')
复制代码
entry

entry: string | [string] object { <key>: string | [string] } (function: () => string | [string] | object { <key>: string | [string] })

// string
entry: 'src/main.js',
// object
entry: {
  main1: "src/main1.js",
  main2: "src/main2.js",
}
// function ,反正这种写法我没见过
entry: () => new Promise((resolve) => resolve(['src/main1.js', './main2.js']))
复制代码
output

path: 输入目录的路径,该路径是一个绝对路径

path: path.resolve(__dirname, 'dist')
复制代码

publicPath: 如果是生产环境,将资源托管到CDN上去,这里的地址是demo

publicPath: process.env.NODE_ENV === 'production' ? '/demo' : '/',
复制代码

filename: 输出文件的名称,这里的[name]可以看做是多个chunk的输出

 filename: '[name].js',
复制代码

chunkFilename: chunk的文件名称

[id].chunk.js
复制代码

sourceMapFilename: 此选项会向硬盘写入一个输出文件,只在 devtool 启用了 SourceMap 选项时才使用

sourceMapFilename: '[file].map'
复制代码

完整的Output的配置,最常用的应该是前面三项

output: {
     path: path.resolve(__dirname, 'dist'),
     publicPath: process.env.NODE_ENV === 'production' ? '/demo' : '/',
     filename: '[name].js',
     chunkFilename: '[id].chunk.js',
     sourceMapFilename: '[file].map',
    
   }
复制代码
module
babel-loader

用来将Es6/Jsx转化为ES5,例子是JSX转化Es5

 module: {
  rules: 
     {
       test: /\.jsx?$/,
       exclude: /node_modules/,
       use: {
         loader: 'babel-loader',
         options: {
           presets: ['es2015', 'react']
         }
       }
     }
     },
复制代码
CSS-loader
      {
         test: /\.css$/,
         // 排除node_modules下面的文件
         exclude: /node_modules/,
         // 处理的顺序从后到前,即先交个css-loader,再交给style-loader
         use: ['style-loader', 'css-loader']
     }
复制代码
Image loader
     {
         test: /\.(jpg|png|gif|svg)$/,
         //可以对图片进行大小限制
         loader: "url-loader?limit=10000
      }
复制代码
reslove
  resolve: {
    extensions: ['.js', '.vue', '.json'],
    alias: {
      'vue$': 'vue/dist/vue.esm.js',
      '@': resolve('src'),
    }
  },
复制代码
pulgin
CommonsChunkPlugin

该插件的作用来用来提取第三方库和公共模块,避免首屏加载的bundle文件或者按需加载的bundle体积过大,从而导致加载时间过长

const CommonsChunkPlugin = require('webpack/lib/optimize/CommonsChunkPlugin');
module.exports = {
     plugins: [
      new CommonsChunkPlugin({
        name: 'polyfills',
        chunks: ['polyfills']
      })
}

复制代码
UglifyJs Plugin

该插件的功能是压缩的js代码

const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
module.exports = {
    plugins: [
    new UglifyJsPlugin()
    ]
}

复制代码
html-webpack-plugin

该插件的作用是生成html文件

const HtmlwebpackPlugin = require('html-webpack-plugin');
module.exports = {
 new HtmlwebpackPlugin({
   title: '',
   filename: 'index.html'
 }),
}
复制代码
设置全局变量
 const webpack = require('webpack');
 module.exports = {
     plugins: [
         new webpack.ProvidePlugin({
           $: 'jquery',
           jQuery: 'jquery'
         })
     ]
 }
复制代码
devServer
devServer: {
      port: METADATA.port,
      host: METADATA.host,
      hot: METADATA.HMR,
      public: METADATA.PUBLIC,
      historyApiFallback: true,
      watchOptions: {

      },

      setup: function(app) {

    },

复制代码
performance
配置性能提示的显示方式。例如,如果您的资产超过250kb,webpack将发出警告通知您。
 performance: {
      hints:
        process.env.NODE_ENV === 'production' &&
        !process.env.VUE_APP_TEST &&
        'warning',
    },
复制代码
其他
vue-cli3.×搭建的项目就配置一个vue.congfig.js'的文件,简化很多了设置, 具体可以看看我的配置

Vue-Cli 3.0从0 开始搭建项目篇1

更多vue-cli3.x相关知识

// 用来加载svg格式的文件
  chainWebpack: config => {
      const svgRule = config.module.rule('svg')
      svgRule
        .use('vue-svg-loader')
          .loader('vue-svg-loader')
    },
复制代码
参考链接

阮一峰webpack-demos

webpack中文网

深入浅出webpack