学习笔记-webpack 入门

webpack 本质上是一个打包工具,它会根据代码的内容解析模块依赖,帮助咱们把多个模块的代码打包。javascript

开始接触wbpack是在vue-cli脚手架中,用于打包、压缩以及一些各个环境的配置,当初花了些时间来研究它,发现里面的可配置项仍是不少的。最近面试中也有问到过关于webpack的配置,今天从新把笔记中的记录结合官网最新的API作了一个整理,以备后续查阅!css

webpack官网地址html

webpack中包含如下几个主要部分:

entry入口:

用来指定一个入口起点(或多个入口起点),进入入口起点后,webpack 会找出有哪些模块和库是入口起点(直接和间接)依赖的。前端

module.exports = {
  entry: './src/index.js'
  }
复制代码

output输出:

output属性告诉webpack在哪里输出它所建立的bundles,以及如何命名这些文件,默认值为./dist。基本上,整个应用程序结构,都会被编译到你指定的输出路径的文件夹中。你能够经过在配置中指定一个output字段,来配置这些处理过程。vue

module.exports = {
  entry: './src/index.js',
  output: {
    filename: 'bundle.js',
    path: path.resolve(__dirname, 'dist')
  }
 }

复制代码

loader解析器:

webpack 可以去处理那些非 JavaScript 文件(webpack 自身只理解 JavaScript),将全部类型的文件转换为webpack可以处理的有效模块,而后你就能够利用 webpack 的打包能力,对它们进行处理。java

module.exports = {
  entry: './src/index.js',
  output: {
    filename: 'bundle.js',
    path: path.resolve(__dirname, 'dist')
  },
  module:{
      rules:[
          {
              test:/\.css$/,
              use:[
                  'style-loader',
                  'css-loader'
              ]
          },
          {
              test:/\.(png|svg|jpg|gif)$/,
              use:[
                  'file-loader'
              ]
          },
          {
              test:/\.(woff|woff2|eot|ttf|otf)/,
              use:[
                  'file-loader'
              ]
          },
          {
              test:/\.(csv|tsv)$/,
              use:[
                  'csv-loader'
              ]
          },
          {
              test:/\.xml$/,
              use:[
                  'xml-loader'
              ]
          }
      ]
  }
};

复制代码

plugins插件:

plugins并非直接操做单个文件,它直接对整个构建过程起做用下面列举了一些咱们经常使用的plugins和他的用插件的范围包括,从打包优化和压缩,一直到从新定义环境中的变量。插件接口功能极其强大,能够用来处理各类各样的任务,例如开启gzip压缩,开发环境去掉警告,debugger,console注释等。node

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');


module.exports = {
    entry: {
        app: './src/index.js'
    },
    module: {
        rules: [
            {
                test: /\.css$/,
                use: ['style-loader', 'css-loader']
            }
        ]
    },
    // 插件管理,需先进行引入,再使用
    plugins: [
        new CleanWebpackPlugin(),
        new HtmlWebpackPlugin({
            title: 'Output Management'
        })
    ],
    output: {
        filename: '[name].bundle.js',
        path: path.resolve(__dirname, 'dist')
    },

};

复制代码

1、非项目环境下的 webpack 的配置以及使用:

此处省略了官网的一步步下载loader包并配置的过程,如需看详细的版本能够移步到官网详细查阅。 当前版本webpack@4.40.2 webpack-cli@3.3.9webpack

关于webpack的下载和初始化:ios

<!--初始化package.json-->

npm init -y

<!--下载webpack-->

npm install webpack webpack-cli --save-dev
复制代码

初始化后的目录以下:git

每一个文件里的具体代码以下:

package.json:

{
  "name": "webpack",
  "version": "1.0.0",
  "description": "",
  "private": true,
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    // 此处配置的build ,可在后期用 npm run build 直接运行压缩打包
    "build": "webpack"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "css-loader": "^3.2.0",
    "csv-loader": "^3.0.2",
    "file-loader": "^4.2.0",
    "style-loader": "^1.0.0",
    "webpack": "^4.40.2",
    "webpack-cli": "^3.3.9",
    "xml-loader": "^1.2.1"
  },
  "dependencies": {
    "lodash": "^4.17.15"
  }
}

复制代码

index.html前台页面:

<!doctype html>
<html>
  <head>
    <title>起步</title>
  </head>
  <body>
  <!--这个bundle.js就是咱们打包后的js压缩文件,配置在webpack.config.js中-->
    <script src="bundle.js"></script>
  </body>
</html>
复制代码

index.js:

import _ from 'lodash';
import './style.css';
import Img from './img.jpg';
import Data from './data.xml'


function component() {
    var element = document.createElement('div');
  
    element.innerHTML = _.join(['Hello', 'webpack!'], ' ');
   
    return element;
  }
  
  document.body.appendChild(component());

复制代码

webpack.config.js配置页面:

const path = require('path');

module.exports = {
<!--这里是入口-->
  entry: './src/index.js',
  
  <!--这里是压缩后的导出-->
  output: {
    filename: 'bundle.js',
    path: path.resolve(__dirname, 'dist')
  },
  
  <!--这里是咱们下载的loader,不一样格式的文件处理-->
  module:{
      rules:[
          {
              test:/\.css$/,
              use:[
                  'style-loader',
                  'css-loader'
              ]
          },
          {
              test:/\.(png|svg|jpg|gif)$/,
              use:[
                  'file-loader'
              ]
          },
          {
              test:/\.(woff|woff2|eot|ttf|otf)/,
              use:[
                  'file-loader'
              ]
          },
          {
              test:/\.(csv|tsv)$/,
              use:[
                  'csv-loader'
              ]
          },
          {
              test:/\.xml$/,
              use:[
                  'xml-loader'
              ]
          }
      ]
  }
};

复制代码

接下来你须要下载package 里面的依赖:

cnpm install
复制代码

执行压缩:

npm run build
复制代码

而后打开index.html 能够看到以下页面:


好了到这里咱们能够正常显示页面了,那接下来能够再添加一些其余文件,css,img,data来压缩试试:

style.css:

.hello{
    color:red;
    font-family: 'MyFont';
    background:url('./img.jpg');

}
复制代码

index.js

import _ from 'lodash';
import './style.css';
import Img from './img.jpg';
import Data from './data.xml'

function component() {
    var element = document.createElement('div');
  
    element.innerHTML = _.join(['Hello', 'webpack'], ' ');
    // 添加css
    element.classList.add('hello');
    
    // 将图像添加到咱们现有到div
    var myImg =new Image();
        myImg.src = Img;

    element.appendChild(myImg)
    
    // 添加数据
    console.log(Data)
    
    return element;
  }
  
  document.body.appendChild(component());

复制代码

而后再执行压缩,查看结果:


压缩后的文件:


页面展现:


到目前为止,咱们实现了将打包都压缩到一个文件中,可是若是是大型项目中的话,这样是不可取的,接下来咱们配置分别将不一样文件压缩并输出不一样的文件。

plugins插件之: HtmlWebpackPlugin( 配置多个文件分别打包 )

新建一个print.js文件在src

npm install --save-dev html-webpack-plugin
复制代码

webpack.config.js配置:

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin'); // 引入

module.exports = {
  // 配置多入口
  entry: {
    app:'./src/index.js',
    print:'./src/print.js'
  },
  //分别打包成不一样名称的js文件
  output: {
    filename: '[name].bundle.js',
    path: path.resolve(__dirname, 'dist')
  },
  // 配置plugins模块
  plugins:[
      new HtmlWebpackPlugin({
          title:'Output Management'
      })
  ]

};
复制代码

执行打包,而后打开index.html,你就会看到 HtmlWebpackPlugin 建立了一个全新的文件,全部的 bundle 会自动添加到 html 中。

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title>Output Management</title>
  </head>
  <body>
  <!--我当前只打包了这两个文件,plugins就帮我都引入到了index.html-->
  <script type="text/javascript" src="app.bundle.js"></script>
  <script type="text/javascript" src="print.bundle.js"></script>
  </body>
</html>

复制代码

打包到dist 文件下

plugins插件之:clean-webpack-plugin( 每次打包清理dist文件夹 )

一般,在每次构建前清理/dist文件夹,也是比较推荐的作法。

npm install clean-webpack-plugin --save-dev
复制代码

webpack.config.js配置:

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');

/*
*此处有坑,在webpack的中文文档中这里的引入方式仍是原来的方式
*const CleanWebpackPlugin = require('clean-webpack-plugin');
*如下是正确的引入方式,小伙伴们请注意哦!
*/

const { CleanWebpackPlugin } = require('clean-webpack-plugin');

module.exports = {
    entry: {
        app: './src/index.js',
        print: './src/print.js'
    },
    output: {
        filename: '[name].bundle.js',
        path: path.resolve(__dirname, 'dist')
    },
    plugins: [
        new CleanWebpackPlugin(),
        new HtmlWebpackPlugin({
            title: 'Output Management'
        })
    ]

};

复制代码

执行后看到,咱们到dist文件中除了index.html 和咱们打包到两个文件,就没有了其余冗余的文件了。

plugins插件之:source-map ( 文件映射 )

webpack 打包源代码时,可能会很难追踪到错误和警告在源代码中的原始位置。例如,若是将三个源文件(a.js, b.js 和 c.js)打包到一个 bundle(bundle.js)中,而其中一个源文件包含一个错误,那么堆栈跟踪就会简单地指向到 bundle.js。这并一般没有太多帮助,由于你可能须要准确地知道错误来自于哪一个源文件。source map 就提供了这个功能。

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');

module.exports = {
    entry: {
        app: './src/index.js',
        print: './src/print.js'
    },
    output: {
        filename: '[name].bundle.js',
        path: path.resolve(__dirname, 'dist')
    },
    // 配置 source-map
    devtool: 'inline-source-map',
    plugins: [
        new CleanWebpackPlugin(),
        new HtmlWebpackPlugin({
            title: 'Output Management'
        })
    ]

};
复制代码

src/print.js中手动添加一条错误

export default function printMe() {
     cosnole.error('I get called from print.js!');
  }

复制代码

打开index页面定位错误信息:


webpack-dev-server 热加载

如今咱们每次修改完内容,还须要用npm run build 执行才会进行打包,这用起来很麻烦,那咱们有没有方法,改变后直接从新打包并刷新页面呢?有的!

npm install --save-dev webpack-dev-server
复制代码

package.json中的script中配置脚本命令,用于开启热加载:

"start": "webpack-dev-server --open",
复制代码

webpack.config.js配置:

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const webpack = require('webpack');

module.exports = {
    entry: {
        app: './src/index.js'
    },
    devtool: 'inline-source-map',
    // 添加热加载
    devServer: {
        contentBase: './dist',
        hot: true
    },
    // 配置css loader,用来后面测试热加载使用
    module: {
        rules: [
            {
                test: /\.css$/,
                use: ['style-loader', 'css-loader']
            }
        ]
    },
    plugins: [
        new CleanWebpackPlugin(),
        new HtmlWebpackPlugin({
            title: 'Output Management'
        }),
        //启动 HMR
        new webpack.NamedModulesPlugin(),
        new webpack.HotModuleReplacementPlugin()
    ],
    output: {
        filename: '[name].bundle.js',
        path: path.resolve(__dirname, 'dist')
    },

};

复制代码

index.js:

import _ from 'lodash';
import printMe from './print.js';
// 添加一个css样式,并引入进来
import './style.css'

function component() {
    var element = document.createElement('div');

    var btn = document.createElement('button');

    element.innerHTML = _.join(['Hello', 'webpack'], ' ');

    btn.innerHTML = 'Click me and check the console!';
    btn.onclick = printMe;

    element.appendChild(btn);

    return element;
}

document.body.appendChild(component());

// 添加热更新,以便当 print.js 内部发生变动时能够告诉 webpack 接受更新的模块

if (module.hot) {
    module.hot.accept('./print.js', function () {
        console.log('Accepting the updated printMe module!');
        printMe();
    })
}

复制代码

执行热加载命令:npm start开启热加载,而后手动更改style.css中的样式,页面会自 动更新,此时就已经完成了webpack的最基础的配置。


2、Vue项目中的webpack配置

上面咱们介绍了非项目中的webpack配置,这一讲咱们来试着在vue项目中配置一下webpack,看看有哪些注意事项。

首先在Vue脚手架的项目中,咱们搭建完成后便可生成如下目录:

项目中的自带webpack版本为: "^3.6.0"


分别有以下三个文件:

1. webpack.base.conf.js

webpack的基础文件,里面用于配置一些关于webpack的基础属性。

2. webpack.dev.conf.js

webpack关于开发环境下的配置文件。

3. webpack.prod.conf.js

webpack关于生产环境下的配置文件。


接下来分享些我项目中的基础配置:

配置babel-polyfill

entry: {
    // 来解析es6的特性
    app: ['babel-polyfill', './src/main.js']
}
复制代码

配置resolve

resolve: {
    // 用于设置自动添加后缀的顺序
    extensions: ['.js', '.vue', '.json'],
    // alias能够映射文件也能够映射路径,用于模块别名,方便后续直接引用别名,例如:@ 表示默认src层
    alias: {
      'vue$': 'vue/dist/vue.esm.js',
      '@': resolve('src'),
    },
     // 避免新增默认文件,编码时使用详细的文件路径,代码会更容易解读,也有益于提升构建速度
    mainFiles: ['index']
  }

复制代码

配置loaderExtractTextPlugin( 抽离css样式 )

ExtractTextPlugin该插件的主要是为了抽离css样式,防止将样式打包在js中引发页面样式加载错乱的现象,会单独打一个css的包出来。这样带来的好处还有,分离出来的cssjs是能够并行下载的,这样能够更快地加载样式和脚本。

{
        test: /\.css$/,
        use: ExtractTextPlugin.extract({
          fallback: 'style-loader',
          use: ['vue-style-loade','css-loader','less-loader', 'postcss-loader'],
        }),
        exclude: /node_modules/,
      },
      {
        test: /\.less$/,
        use: ExtractTextPlugin.extract({
          fallback: 'style-loader',
          use: ['css-loader?modules', 'less-loader', 'postcss-loader'],
        }),
      }
      

复制代码
plugins: [
    new ExtractTextPlugin("styles.css")
    ]

复制代码

配置loader 之减小loader 编译范围 excludeinclude

include 表示哪些目录中的 .js 文件须要进行 babel-loader

exclude 表示哪些目录中的 .js 文件不要进行 babel-loader

咱们在使用 loader 的时候,尽量把 loader 应用的文件范围缩小,只在最少数必须的代码模块中去使用必要的 loader,例如 node_modules 目录下的其余依赖类库文件,基本就是直接编译好可用的代码,无须再通过 loader 处理了:

exclude:

{
        test: /\.(js|vue|jsx)$/,
        loader: 'eslint-loader',
        exclude: /node_modules/,
        enforce: 'pre',
        options: {
          fix: true
        }
      }

复制代码

include:

{
        test: /\.js$/,
        use: [{
          loader: 'babel-loader'
        },
        {
          loader: 'iview-loader',
          options: {
            prefix: false
          }
        }
        ],
        include: [resolve('src'), resolve('test'), resolve('node_modules/webpack-dev-server/client'), resolve('node_modules/iview/src')]

复制代码

下面就把我整理过的这三个文件的配置完整文件分享给你们:

webpack.base.conf.js基础配置文件:

'use strict'
const path = require('path')
const utils = require('./utils')
const config = require('../config')
const vueLoaderConfig = require('./vue-loader.conf')
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');

function resolve(dir) {
  return path.join(__dirname, '..', dir)
}

module.exports = {
  context: path.resolve(__dirname, '../'),
  entry: {
    // 配置babel-polyfill 来解析es6的特性
    app: ['babel-polyfill', './src/main.js']
  },
  output: {
    path: config.build.assetsRoot,
    filename: '[name].js',
    publicPath: process.env.NODE_ENV === 'production'
      ? config.build.assetsPublicPath
      : config.dev.assetsPublicPath
  },
  //  其余解决方案
  resolve: {
    extensions: ['.js', '.vue', '.json'],
    alias: {
      'vue$': 'vue/dist/vue.esm.js',
      '@': resolve('src'),
    },
    mainFiles: ['index']
  },
  module: {
    rules: [
      {
        test: /\.vue$/,
        use: [{
          loader: 'vue-loader',
          options: vueLoaderConfig
        },
        {
          loader: 'iview-loader',
          options: {
            prefix: false
          }
        }]
      },
      {
        test: /\.js$/,
        use: [{
          loader: 'babel-loader'
        },
        {
          loader: 'iview-loader',
          options: {
            prefix: false
          }
        }
        ],
        include: [resolve('src'), resolve('test'), resolve('node_modules/webpack-dev-server/client'), resolve('node_modules/iview/src')]
      },
        // ExtractTextPlugin 用于将css文件从js文件中拆出来,单独打成一个包,
      {
        test: /\.css$/,
        use: ExtractTextPlugin.extract({
          fallback: 'style-loader',
          use: ['vue-style-loade','css-loader','less-loader', 'postcss-loader'],
        }),
        exclude: /node_modules/,
      },
      {
        test: /\.less$/,
        use: ExtractTextPlugin.extract({
          fallback: 'style-loader',
          use: ['css-loader?modules', 'less-loader', 'postcss-loader'],
        }),
      },
        // 把小于limit阀值大小的图片转为base64字符串          
      {
        test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
        loader: 'url-loader',
        options: {
          limit: 10000,
          name: utils.assetsPath('img/[name].[hash:7].[ext]')
        }
      },
      {
        test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
        loader: 'url-loader',
        options: {
          limit: 10000,
          name: utils.assetsPath('media/[name].[hash:7].[ext]')
        }
      },
      {
        test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
        loader: 'url-loader',
        options: {
          limit: 10000,
          name: utils.assetsPath('fonts/[name].[hash:7].[ext]')
        }
      },
      {
        test: /\.(js|vue|jsx)$/,
        loader: 'eslint-loader',
        exclude: /node_modules/,
        enforce: 'pre',
        options: {
          fix: true
        }
      }

    ]
  },
  plugins: [
    /**
     * 将样式提取到单独的css文件,而不是内嵌到打包的js文件中。
     * 这样带来的好处时分离出来的css和js是能够并行下载的,
     * 这样能够更快地加载样式和脚本。
     */
    new ExtractTextPlugin("styles.css"),

    // 清空输出文件夹以前的输出文件
    new CleanWebpackPlugin(),
  ],
  node: {
    // prevent webpack from injecting useless setImmediate polyfill because Vue
    // source contains it (although only uses it if it's native). setImmediate: false, // prevent webpack from injecting mocks to Node native modules // that does not make sense for the client dgram: 'empty', fs: 'empty', net: 'empty', tls: 'empty', child_process: 'empty' } } 复制代码

webpack.dev.conf.js开发环境配置文件:

'use strict'
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.conf')
const CopyWebpackPlugin = require('copy-webpack-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin')
const portfinder = require('portfinder')
const OpenBrowserPlugin = require('open-browser-webpack-plugin')

const HOST = process.env.HOST
const PORT = process.env.PORT && Number(process.env.PORT)

// 将基本配置合并到开发环境
const devWebpackConfig = merge(baseWebpackConfig, {
  module: {
    rules: utils.styleLoaders({ sourceMap: config.dev.cssSourceMap, usePostCSS: true })
  },
  // cheap-module-eval-source-map is faster for development
  devtool: config.dev.devtool,

  // these devServer options should be customized in /config/index.js
  devServer: {
    clientLogLevel: 'warning',
    historyApiFallback: {
      rewrites: [
        { from: /.*/, to: path.posix.join(config.dev.assetsPublicPath, 'index.html') },
      ],
    },
    hot: true,
    contentBase: false, // since we use CopyWebpackPlugin.
    compress: true,
    host: HOST || config.dev.host,
    port: PORT || config.dev.port,
    open: config.dev.autoOpenBrowser,
    overlay: config.dev.errorOverlay
      ? { warnings: false, errors: true }
      : false,
    publicPath: config.dev.assetsPublicPath,
    proxy: config.dev.proxyTable,
    quiet: true, // necessary for FriendlyErrorsPlugin
    watchOptions: {
      poll: config.dev.poll,
    }
  },
  plugins: [
    // vue run dev后自动打开浏览器插件
    new OpenBrowserPlugin({url: 'http://localhost:8080' }),

    new webpack.DefinePlugin({
      'process.env': require('../config/dev.env')
    }),
    
    // 模块热替换,无需整个刷新页面
    new webpack.HotModuleReplacementPlugin(),
    new webpack.NamedModulesPlugin(), // HMR shows correct file names in console on update.
    new webpack.NoEmitOnErrorsPlugin(),
   
    // https://github.com/ampedandwired/html-webpack-plugin
    new HtmlWebpackPlugin({
      filename: 'index.html',
      template: 'index.html',
      inject: true
    }),
    // copy custom static assets
    // 拷贝插件
    new CopyWebpackPlugin([
      {
        from: path.resolve(__dirname, '../static'),
        to: config.dev.assetsSubDirectory,
        ignore: ['.*']
      }
    ]),
    // 去除依赖中重复的插件
    new webpack.optimize.DedupePlugin() ,

    /**
     * 为组件分配ID,经过这个插件webpack能够分析和优先考虑使用最多的模块,
     * 并为它们分配最小的ID
     */
    new webpack.optimize.OccurrenceOrderPlugin()
  ]
})

module.exports = new Promise((resolve, reject) => {
  portfinder.basePort = process.env.PORT || config.dev.port
  portfinder.getPort((err, port) => {
    if (err) {
      reject(err)
    } else {
      // publish the new Port, necessary for e2e tests
      process.env.PORT = port
      // add port to devServer config
      devWebpackConfig.devServer.port = port

      // Add FriendlyErrorsPlugin
      devWebpackConfig.plugins.push(new FriendlyErrorsPlugin({
        compilationSuccessInfo: {
          messages: [`Your application is running here: http://${devWebpackConfig.devServer.host}:${port}`],
        },
        onErrors: config.dev.notifyOnErrors
        ? utils.createNotifierCallback()
        : undefined
      }))

      resolve(devWebpackConfig)
    }
  })
})

复制代码

webpack.prod.conf.js生产环境的配置文件:

'use strict'
const version = require('../package.json').version || '';
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 UglifyJsPlugin = require('uglifyjs-webpack-plugin')
const zip = require('zip-webpack-plugin')

const env = require('../config/prod.env')

// 将基本配置合并到生产环境
const webpackConfig = merge(baseWebpackConfig, {
  module: {
    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: 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
    }),
    // 对js文件进行压缩
    new UglifyJsPlugin({
      extractComments: {
        // 根据条件保存须要保留的注释
        condition: function (a, data) {
          return /app.\w+.js$/.test(data.file);
        },
        //存储提取的注释的文件名调用
        banner: 'version:' + version,
      },

      // 部分格式化,根据须要配置
      uglifyOptions: {
        compress: {
          warnings: false,      // 自动删除警告
          drop_console: true,   // 自动删除console.log
          typeofs: false,  //将typeof foo==“未定义”转换为foo==void 0。注意:对于IE10和早期版本有问题。
        }
      },
      sourceMap: config.build.productionSourceMap,
      parallel: true
    }),
    // extract css into its own file 
    // 将css 提取到本身的文件中
    new ExtractTextPlugin({
      filename: utils.assetsPath('css/[name].[contenthash].css'),
      // Setting the following option to `false` will not extract CSS from codesplit chunks.
      // Their CSS will instead be inserted dynamically with style-loader when the codesplit chunk has been loaded by webpack.
      // It's currently set to `true` because we are seeing that sourcemaps are included in the codesplit bundle as well when it's `false`, 
      // increasing file size: https://github.com/vuejs-templates/webpack/issues/1110
      allChunks: true,
    }),
    // Compress extracted CSS. We are using this plugin so that possible
    // duplicated CSS from different components can be deduped.
    new OptimizeCSSPlugin({
      cssProcessorOptions: config.build.productionSourceMap
        ? { safe: true, map: { inline: false } }
        : { 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
    new HtmlWebpackPlugin({
      filename: config.build.index,
      template: 'index.html',
      inject: true,
      minify: {
        removeComments: true,
        collapseWhitespace: true,
        removeAttributeQuotes: true
        // more options:
        // https://github.com/kangax/html-minifier#options-quick-reference
      },
      // necessary to consistently work with multiple chunks via CommonsChunkPlugin
      chunksSortMode: 'dependency'
    }),
    // keep module.id stable when vendor modules does not change
    new webpack.HashedModuleIdsPlugin(),
    // enable scope hoisting
    new webpack.optimize.ModuleConcatenationPlugin(),
    // split vendor js into its own file
    new webpack.optimize.CommonsChunkPlugin({
      name: 'vendor',
      minChunks(module) {
        // 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
    new webpack.optimize.CommonsChunkPlugin({
      name: 'manifest',
      minChunks: Infinity
    }),
    // This instance extracts shared chunks from code splitted chunks and bundles them
    // in a separate chunk, similar to the vendor chunk
    // see: https://webpack.js.org/plugins/commons-chunk-plugin/#extra-async-commons-chunk
    // CommonsChunkPlugin:提取通用模块文件,vue vuex vue-router axios
    new webpack.optimize.CommonsChunkPlugin({
      name: 'app',
      async: 'vendor-async',
      children: true,
      minChunks: 3
    }),

    // 拷贝插件
    new CopyWebpackPlugin([
      {
        from: path.resolve(__dirname, '../static'),
        to: config.build.assetsSubDirectory,
        ignore: ['.*']
      }
    ]),
    // 打成zip包,通常用于上线
    new zip({
      path: './',
      filename: `frame-fe.zip`
    }),
    /**
     * 将原来的 chunk 分红更小的 chunk
     * 直到各个 chunk 的大小达到 option 设置的 maxSize
     */
    new webpack.optimize.AggressiveSplittingPlugin({
			minSize: 30000,
			maxSize: 50000
		}),
  ]
})

if (config.build.productionGzip) {
  const CompressionWebpackPlugin = require('compression-webpack-plugin')

  // 开启gzip压缩 gzip能在本来压缩的基础上再进行压缩50%以上!!!
  webpackConfig.plugins.push(
    new CompressionWebpackPlugin({
      asset: '[path].gz[query]',
      algorithm: 'gzip',
      test: new RegExp(
        '\\.(' +
        config.build.productionGzipExtensions.join('|') +
        ')$'
      ),
      threshold: 10240,
      minRatio: 0.8
    })
  )
}

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

module.exports = webpackConfig


复制代码

编写时间紧张,内容稍有粗糙,正在改进中,请见谅!


参考文献:

webpack中文文档

webpack配置文档

webpack构建指南

webpack-预处理-loader

webpack-插件-plugins

webpack-更多第三方插件

webpack开启gzip压缩

前端大全-一看就懂的webpack高级配置与优化

还有些参考文献当时忘记保存,后续会陆续添加上,感谢阅读!


邮箱:christine_lxq@sina.com

未完待续.....

做者:Christine    
    出处:https://juejin.im/user/594c9772128fe10065110aa5/posts
    版权全部,欢迎保留原文连接进行转载:但愿看到个人最新文章的能够添加下关注哦!:) 
复制代码
相关文章
相关标签/搜索