webpack学习笔记

824 阅读13分钟

第二章

 2.1 节
    初始化webpack npm init 
                  npm i webpack-cli --save 
                  npm i weboack --save
    webpack 打包处理文件   npx webpack index.js
 2.2 节
    webpack:模块打包工具 (es module AMD CMD COMMOM.JS)       
    common.js : 引入 require('header.js')   导出 module.exports = Header;
2.3 节
    package.json 文件
           "private": true, // 禁止发布到npm上     
           "main": "index.js" // 向外暴露文件       
2.4 节
    打包输出信息
     hash 打包对应唯一hash值
     asset 打包输出文件
     chunks 每个js文件对应的id
     chunkname  每个文件对应的name   

第三章

3.1 节
  ① 创建 webpack.config.js 配置文件
    const path = require('path');
    module.exports = {
        entry: './src/index.js',
        output: {
            filename: 'bundle.js',
            path: path.resolve(__dirname, 'dist')
        }
    };
    打包命令: npx webpack --config webpack.config.js
  ② bable-loader 资源管理
    loader 告诉如何对文件进行打包,webpack 只能识别js文件
    图片资源: file-loader
    webpak.config.js 配置如下:
            module: {
                rules: [{
                    test: /\.(png|jpg|gif)$/,
                    use: [
                        'file-loader'
                    ]
                }]
            },
3.2 节
   ① 打包后文件名与打包前一致: 
       webpack.config.js 中配置
            use: {
                loader: 'file-loader',
                options: {
                    //  placeholder: 占位符
                    name: '[name].[ext]',   // name 打包前名字  ext打包文件后缀
                    outputPath: './images'   // 打包后制定图片位置
                }
            }
    ② url-loader 
      会将图片转base64 在js中进行加载,与file-loader不同,
      缺点:图片过大,js就无法加载,等待时间过长。
      优点:可以加载 小图片 ,减少http请求,大图片使用 url-loader。
      配置如下: 
      rules: [{
        test: /\.(png|jpg|gif)$/,
        use: {
            loader: 'url-loader',
            options: {
                name: '[name]_[hash].[ext]',
                outputPath: 'images/',   // 图片大于2048时, 将图片打包在images文件下
                limit: 4048,    // 图片小于2048时,将图片转base64 打入js文件中 4kb
            },
        }
      }]
3.3 节
 loader 样式
    css-loader css文件的关系与互相引用识别
    style-loader  css样式的绑定
    sass-loader  scss 文件使用
    node-sass  scss 文件使
    配置如下:
         webpack.config.js文件
        {
            test: /\.scss$/i,
            use: ['style-loader', 'css-loader', 'sass-loader'],
        }
    postcss-loader  为css添加浏览器前缀 如-webkit 等,
    配置如下:
         1. webpack.config.js文件。
        {
            test: /\.scss$/i,
            use: ['style-loader', 'css-loader', 'sass-loader', 'postcss-loader'],
        }
        2. 创建 postcss.config.js 文件配置 posstcss
        module.exports = {
            plugins: [
                require('precss'),
                require('autoprefixer')
            ]
        }
        如果报错:Cannot find module 'autoprefixer',则 npm install --save precss 来解决
3.4 节
   loader详细配置
      ① css-loader
         {
            loader: 'css-loader',
            options: {
                importLoaders: 2  // 0 => 无 loader(默认); 1 => postcss-loader; 2 => postcss-loader, sass-loader 
            }
         }
       ② 模块化css,防止css污染全局 modules: true 
         webpack.config.js 配置
         {
            loader: 'css-loader',
            options: {
                importLoaders: 2  // 0 => 无 loader(默认); 1 => postcss-loader; 2 => postcss-loader, sass-loader 
                modules: true    // 防止css样式污染全局
            }
        }
        引入css
            import style from './index.scss';
            img1.classList.add(style.avatar);
3.5 节 pulgins 使用
    在打包的某个时刻,可以利用插件来帮助你开发。
    ① HtmlWebpackPlugin 插件: 在dist文件中生成html 文件,可以为html文件指定template, 为html页面绑定打包后的bundle.js 文件
      安装:    
         npm install --save-dev html-webpack-plugin
      引入: webpack。config.js
         var HtmlWebpackPlugin = require('html-webpack-plugin'); 
      使用: webpack。config.js
        plugins: [
            new HtmlWebpackPlugin({
                template: 'src/index.html'  // 设置指定html模板
            })
       ]
    ② cleanWebpackPlugin 插件,每次打包清除dist目录下文件
      使用: plugins:[ new CleanWebpackPlugin() ]
3.6 节 entry output
    ① 打包多个入口文件
      entry配置:
        entry: {
            main: './src/index.js',
            home: './src/index_copy.js'
        },
      output配置:  [name].js 配置输出文件名为入口文件名。 
        output: {
            filename: '[name].js',
            path: path.resolve(__dirname, 'dist')
        },
3.7 节 source-map 设置
 .map 文件:打包后生成的.map文件,就是源文件与打包后的文件的映射文件。
 Inline-source-map:将映射文件.map文件直接写入打包js文件中
 Cheap-Inline-source-map:Cheap提示错误是行就行,不需要精确到列。只映射业务代码,不包含第三方插件
 Cheap-module-source-map:映射业务代码同时,也映射第三方插件,提示错误行位置.
 Eval 通过eval 方式执行模式指向当前js文件,不会生成map文件,复杂内容可能提示不全面。
 
    提供源代码映射后,确定源代码错误位置
    ① 选择不同的source-map,增强调试过程。
        使用: webpack.config.js中配置
        devtool: 'source-map',     // 提示原始源代码错误位置
        
    ② 以下map类型,具体使用参考文档,按照(速度,生产环境,开发环境,品质等区分):
      https://www.webpackjs.com/configuration/devtool/ 
        inline-cheap-module-source-map   原始源代码(仅限行)
        source-map 原始源代码,会新增map映射文件
        inline-source-map 原始源代码  map映射文件直接打包到js文件中
        
    ③ 推荐使用development环境: cheap-module-eval-source-map  
      推荐使用production环境: cheap-module-source-map    
3.8 节 使用webpack devServer
    更改代码时,可以实时打包并更新更改的内容。 三种方法如下:
    ① packjion.json 内配置
      "scripts": {
        "bundle": "webpack --watch"
      },
    ② webpack.config.js 配置
      devServer: {
         contentBase: "./dist",
      }
      package,json 配置
      "scripts": {
        "bundle": "webpack --watch",
        "start": "webpack=dev-server"
      },
      如果报错:则安装 npm i webpack-dev-server -d
    ③ 创建webpack打包判断文件 
      安装webpack中间件
        npm i express webpack-dev-middleware -d

      创建server.js
        const express = require('express');
        const webpack = require('webpack');
        const webpackDevMiddleware = require('webpack-dev-middleware');
        const config = require('./webpack.config.js');
        const complier = webpack(config);
        const app = new express();
        // 通过express启动一个服务器, 通过webpack 中间件webpackDevMiddleware监听文件变化,然后重新执行打包 complier
        app.use(webpackDevMiddleware(complier, {
            publicPath: config.output.publicPath
        }))
        app.listen(3000, () => {
            console.log('server is running');
        })

      package.json文件修改
        "scripts": {
            "server": "node server.js"
        },

      运行打包: npm run start

3.9 节 热模块更新
    功能:HMR 在运行时更新各种模块,而无需进行完全刷新。
    ① 更改部分刷新
      weboack.config.js 配置
      plugins: [
          new CleanWebpackPlugin(),
          new webpack.HotModuleReplacementPlugin()
      ]
      devServer: {
          hot: true   
      },
      运行: npm run start  (webpack-dev-server)
    ② 更改模块时,想指定模块刷新并且 还原初始值
      index.js 添加: 当module热更新时,指定print.js 模块做响应处理
      if (module.hot) {
          module.hot.accept('./print.js', function() {
          console.log('Accepting the updated printMe module!');
          printMe();
        })
      }
3.11-3.12 babel-loader 处理ES6
   babel-loader是解析es6的桥梁,需要通过插件翻译es5,如babel-perset
   babel-core: 把js代码部分解析成ast,有些新语法在低版本js中不存在的,如箭头函数,rest参数,通过ast语法转换器分析其语法后转换低版本js。
   babel-prset:代表乙烯类转码插件,提供预设,为es5转码。
   babel-poly-fill: 转换babel preset没有的es6新特性,打包js会变大。
   transform-runtime:  babel-poly-fill 会污染全局变量,transform-runtime 转换es6时不会污染全局。
   ①   
    npm install @babel/core @babel/preset-env 
    npm install --save @babel/polyfill
    webpack.config.js配置:
      {
            test: /\.js$/,
            exclude: /node_modules/,
            loader: "babel-loader",
            options: {
                // 使用 babel-poly-fill 会转化所有低版本没有的es6语法,会加大打包文件大小。
                // 使用 { useBuiltIns: 'usage' },仅转换使用的es6语法从而见效打包文件大小。可以不引入babel-poly-fill 该配置自动转换es6用的语法。
                // https://babel.docschina.org/docs/en/babel-preset-env#targets 配置不同场景需要 babel=poly-fill
                "presets": ["@babel/preset-env", { useBuiltIns: 'usage' }],   
            }
      }
    index.js 引入 import "@babel/polyfill";

    ②
     npm install --save-dev @babel/plugin-transform-runtime
      {
            test: /\.js$/,
            exclude: /node_modules/,
            loader: "babel-loader",
            options: {
                "plugins": [
                    [
                        "@babel/plugin-transform-runtime",
                        {
                            "corejs": 2,
                            "helpers": true,
                            "regenerator": true,
                            "useESModules": false
                        }
                    ]
                ]
            }
        }
   * 配置 {corejs: 2 }作用有时Babel可能会在输出中注入一些相同的代码,因此可能会重复使用。使用类转换(没有松散模式)
     使用 core.js : 2 需要安装插件:
     npm install --save @babel/runtime-corejs2
      
  ③ 如果私有功能:可以使用babel-poly-fill
    如果是库功能:使用transfrom-runtime,来规避全局变量冲突。

  ④ 插件配置优化,单独提出公共文件
    创建 . .babelrc 文件
    让插件config内容写入:
        {
            "plugins": [
                [
                  "@babel/plugin-transform-runtime",
                {
                  "corejs": 2,
                  "helpers": true,
                  "regenerator": true,
                  "useESModules": false
              }
            ]
          ]
      }
      npx webpack 打包
      
3.13 节 配置react打包
     安装 react react-dom
     npm i react react-dom --save
     npm i @babel/preset-env @babel/preset-react
     
     webpack.config.js配置:
        "presets": [
            "@babel/preset-env", 
              // 一下浏览器才会添加 babel-poliy-fill
            "@babel/preset-react"
    ]

    js文件引入import "@babel/polyfill";

4.1节 tree-shaking 概念
    概念:通常用于描述移除 JavaScript 上下文中的未引用代码(dead-code)。
    tree-shaking: 只支持静态引入 如export 不支持require 动态引入。

    webpack.config.js 文件配置tree-shaking :
      optimization: {
            useExports: true    //打包使用部分
      },

    package.json 文件配置;
        tree-shaking 会处理没有暴露方法的插件,如 @babel-poly-fill。会使打包报错。所以配置如下解决问题:
        @babel-poly-fill 是在window上绑定es6语法 如window,pormise,不会向外暴露方法,
        "sideEffects": false,// 禁止tree-shaking 处理不向外暴露方法的插件,将文件标记副作用
        "sideEffects": ['@babel-poly-fill'] // 或针插件配置如下:  tree-shaking不会处理该插件
    
        注意: trees-shaking 可以配置mode:'production', 来展示效果。

4.2 development production区分
    拆分配置 devlopment 开发模式,和production 生产模式
    ① 创建 webpack.base.js  创建公共webpack配置文件
    ② 创建 webpack.dev.js 创建开发模式webpack配置文件,配置dev环境下私有配置
    ③ 创建 webpack.prod.js 创建生产模式webpack配置文件,配置prod 环境下私有配置
    ④ 合并 webpack.base.js 和 webpack.dev.js 配置文件
      npm install --save-dev webpack=merge
      webpack.dev.js 配置如下:
      module.exports = merge(common, {
          mode: 'development',
          devServer: {
              contentBase: "./dist",
              open: true,
              compress: true,
              hot: true    
          },

          plugins: [
              new webpack.HotModuleReplacementPlugin()
          ],
      });
      ⑤ 合并webpack.prod.js webpack.base.js  与以上配置相同。
      ⑥ package.json 配置
            "scripts": {
                "dev": "webpack-dev-server --config webpack.dev.js",
                "build": "webpack --config webpack.prod.js"
        },
      ⑦ 运行项目
        npm run dev
        npm run build 

4.3-4.4 code spliting ( 代码分割 代码拆分进行性能优化 )
        npm i babel-plugin-dynamic-import-webpack --save -dev
      ① 同步导入代码拆分
        webpack.config.js配置
       https://webpack.js.org/configuration/optimization/#root
          optimization: {
            runtimeChunk: {
                name: 'runtime'
            },
            usedExports: true,
               splitChunks:{
                  Chunks:”all”,   // 分割所有引入的模块(同步引入和异步引入模块)
                  minSize: 3000,   // 模块文件大于30kb,才被分割
                  minChunks: 1,   // 模块使用次数最少一次
                  maxAsyncRequests: 5,  // 同时请求次数大于5
                  maxInitialRequests: 3,
                  automaticNameDelimiter: “ ~ ”,   // 分割文件名称链接符号 
                  Name: true,
                  cacheGroups: {   // 缓存组
                      Vendors: {
                      Test: /[\\/]node_modules[\\/]/,  // 引入模块是 nodemoudle中的
                          Priority: -10,   // 分割优先级 为-10
                          Filename: “vendors.js”,  // 分割后文件名
                      }, 
                      Deafault: {   // 不在node-module中的模块,分割组
                          Priority: -20,   // 分割优先级
                          reuseExistingChunk: true,   // 一个模块多个地方引用,不会重复分割,会在统一分割模块中引用
                          Filename: “common.js”    // 分割后文件名
                      }
            }
            },
      ② 异步导入代码拆分 如 import .promise()
        需要使用像 Babel 这样的预处理器和Syntax Dynamic Import Babel Plugin
        "plugins": ["@babel/plugin-syntax-dynamic-import"]


 4.8 打包分析 preloading prefetching
 使用 Analyse进行打包后文件的分析http://webpack.github.com/analys
 配置如下: package.json文件中写入
 “script”:{
   “build”:  “webpack --profile --json”  //  生成stats.json 文件,对打包过程进行描述
 }
Commit + shift +p  搜做 coverage看文件利用率

 增加文件利用率方法:
1.未执行方法可单独写js,然后异步引入文件,这可以增加文件使用率。
2.Import 异步引入文件 + prefetching 增加文件利用率
  Webpack 配置prefetching: 该配置可在主要文件加载后,加载其他文件
  主文件加载后,空闲时间加载 click.js 文件,优化click.js 使用时速度,同时增加文件利用率。
     document.addEventListener(“ click” , () => {
         Import( /*  webpackLoad: true */  “./click.js”)
         .then(({ default: func }) => {
              Func() 
         })
     })
3.preLoading 同住文件一同加载
4.9节 css 代码拆分
  概念: 将css多个文件单独打包出来一个css文件
   1. chunkFilename:间接引入文件打包后文件名 
   2. css拆分插件:MiniCssExtractPlugin
      webpack.config.js配置如下:
      plugins: [
          new MiniCssExtractPlugin({
            filename: '[name].css',
            chunkFilename: '[id].css',
            ignoreOrder: false, // Enable to remove warnings about conflicting order
          }),
      ],
      rules: [
            {
              test: /\.css$/,
              use: [
                {
                  loader: MiniCssExtractPlugin.loader,  // css文件使用 MiniCssExtractPlugin插件loader 
                },
                'css-loader',
              ],
            },
  3. 优化css,合并css。使用Optimize CSS Assets Webpack Plugin 插件
     合并前:
       body{font-size:12px}
       body{background: #ccc}
     合并后: body{ font-size:12px; background: #ccc}
    ① 插件引入
      const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
    ② 插件使用
      module.exports = {
        optimization: {
          minimizer: [new OptimizeCSSAssetsPlugin({})],
      },
  4. 注意:如果打包以上配置后,css文件没有单独打包分离,请查看tree-shaking配置
     如果配置:
     optimization: {
        usedExports: true
     }
     请 在pageagejson文件中配置:
        "sideEffects": [
            "*.css"
        ],
    让 tree-shaking忽略css文件,

4.10 缓存

1. 文件过大提示报错:WARNING in asset size limit: The following asset(s) exceed the recommended size limit (244 KiB).
    配置 webpack.config.json
    performance: false;
2. 浏览器合理缓存
   ① 打包后文件生成hash值,当hash值变化时,浏览器更新缓存。
    output: {
        filename: '[name].[contenthash].js',     // 配置hash值
        path: path.resolve(__dirname, '../dist'),
    },
   ② 老版本webpack不兼容时,是包和包之间的关系相同部分 mainfest 发生改变,是文件没改变,但hash值变了。解决如下: 
    optimization: {
      runtimeChunk: {
          name: 'runtime'
      },
    }

4.11 shimming

 概念:全局变量
 ① js中使用$符号,未引入jquery。打包报错 $ is not defined
   webpack打包会模块化打包,不同模块引入jquert库不会公用。
    export function ui() {
      $('body').css('background', 'red');
    }
 ② 配置:只要文件中使用$ 符号,默认引入jquery
   new webpack.ProvidePlugin({
        _: 'lodash',
        $: 'jquery'
   })
 ① 配置this指向: imports-loader插件
   模块化打包,输出this指向当前模块,不指向window,如何将this指向window:
   安装 npm i imports-loader --save
   使用 rules: [
          {
            test: require.resolve('index.js'),
            use: 'imports-loader?this=>window'
          }
        ]

4.12 配置好环境变量

    env.production env.development
    根据package.json的env 变量,判断打包配置文件: 
    ① 配置接受env环境变量接受函数; webpack.base.js文件
      module.exports = (env) => {
          if (env && env.production) {
              //  正式环境
              return merge(commonConfig, production);
          } else {
              // 开发环境
              return merge(commonConfig, development)
          }
      }
         注:commonConfig 是公共webpack.base.js 配置
             production 是正式环境 webpack.prod.js 配置
             development 是开发环境 webpack.dev.js 配置
    ② pageage.json 传入env环境变量
          "scripts": {
                "dev": "webpack-dev-server --env.development  --config ./build/webpack.dev.js",
                "build": "webpack --env.production --config ./build/webpack.base.js"
            },
    ③ 打包
      npm run build 
      npm run dev
    env 其他传入方式
       1.  传入 "build": "webpack --env production --config ./build/webpack.base.js"
           接收  module.exports = (production) => { if(production )  { .....}}
       
       2.  传入 "build": "webpack --env.production == prod --config ./build/webpack.base.js"
           接收 module.exports = (env) => { if( env.production == prod  )  { .....}}

第五章

5.1 节 libiary
    创建公共库,提供支持各种引入方式
    npm init - y
    ①  导出公共库
      import * as math from './math.js'
      import * as string from './join.js'
      export default {
          math,
          string
      }
    ② 导出库不支持 import commom <script> 引入,需要如下配置:
     output: {
        path: path.resolve(__dirname, 'dist'),
        filename: '[name].js',
        libraryTarget: 'umd',  // 不同方式暴露 libriary 库 (umd ,window ,this)
        library: 'library'  // 公开为名为的变量
    }
    ③ 引入库
      <script src="./main.js"></script>
      <script>
          console.log(library.add())
      </script> 
    注意:如公共库引入插件如lodash ,引入公共库项目中也使用 lodash,
         会是打包两次lodash插件,是打包后文件过大,解决如下:
      externals: {  // 如果用户安装好了lodash,放弃对外部 library 的控制
        lodash: {
          commonjs: 'lodash',  // commom.js 引入时,必须用lodash变量名引入 cosnt lodash = require(‘lodash)
          commonjs2: 'lodash',
          amd: 'lodash',
          root: '_'
        }
      }
    ④ pageage.json 配置
      向外暴露打包生成的库
      “main”:"./dist/main.js"; 
    ⑤ 发布库 : 使用npm 发布
      npm 注册账号
      https://www.npmjs.com/package/npm
      npm adduser
      npm publish
      案例:https://www.jianshu.com/p/572de9b413b2

5.2节 PWA打包配置( runtimeChunk web application)
      1. 开启本地服务器
        安装: npm install workbox-webpack-plugin --save-dev
        添加: package.jspn
            "build": "webpack",
            "start": "http-server dist"  // htip-server 开启dist目录服务
        启动:npm run build
             npm run start
      总结: 服务关闭后,页面刷新,显示服务器挂掉
      2. 实现服务器关闭后,页面刷新,依然保留页面, PWA技术实现
         安装 :npm install workbox-webpack-plugin --save-dev
         配置: webpack.prod.config .js
           const WorkboxPlugin = require('workbox-webpack-plugin');
                plugins: [
                    new WorkboxPlugin.GenerateSW({
                        // these options encourage the ServiceWorkers to get in there fast
                        // and not allow any straggling "old" SWs to hang around
                        clientsClaim: true,
                        skipWaiting: true
                    })
                ]
                index.ja 文件
                // 进行 service-wroker 注册
                if ('serviceWorker' in navigator) {
                    window.addEventListener('load', () => {
                        navigator.serviceWorker
                            .register('./service-worker.js')
                            .then(registration => {
                                console.log('====== this is inner console ======')
                                console.log('SW registered: ', registration);
                            })
                            .catch(registrationError => {
                                console.log('SW registration failed: ', registrationError);
                            });
                    });
                }
            运行: npm run build  
                  npm start

5.3节 typescript 配置

    typescript 规范代码. 提高js可维护行。
    ① 安装: npm i ts-loader typescript -D
      引入 :webpack.config.js文件中添加解析typescript代码的loader
            module: {
                rules: [
                    {
                        test: /\.ts$/,
                        loader: 'ts-loader',
                        exclude: /node_modules/
                    }
                ]
            },
    ② 根目录文件下新增个.tsconfig.json文件
      {
        "compilerOptions": {
                "outDir": "./dist/", // 默认解析后的文件输出位置
                "noImplicitAny": true, // 存在隐式 any 时抛错
                "module": "es6", // 表示这是一个es6模块机制
                "target": "es5", // 表示要讲ts代码转成es5代码
                "allowJs": true // 表示允许引入js文件。TS 文件指拓展名为 .ts、.tsx 或 .d.ts 的文件。如果开启了 allowJs 选项,那 .js 和 .jsx 文件也属于 TS 文件
            }
        }
     ③ 添加ts文件
        class Greeter {
              greeting: string;
              constructor(message: string) {
                  this.greeting = message;
              }
              greet() {
                  return "Hello, " + this.greeting;
              }
          }

          let greeter = new Greeter("world");

          let button = document.createElement('button');
          button.textContent = "Say Hello";
          button.onclick = function() {
              alert(greeter.greet());
          }
          document.body.appendChild(button);
      ⑥ 打包 npm run build 看能否正常运行ts文件
        typescript 提供代码校验,如果引入第三方插件想支持ts 校验提示需要安装对应 @types插件
        如使用lodash插件,需要安装 npm install --save-dev @types/lodash
        提醒:ts使用的包,可通过https://microsoft.github.io/TypeSearch 这个网址去查对应的包使用指南

5.4节 webpack.devServer 实现请求转发

      线上接口 http://www.dell-lee.com/react/api/header.json 
      ① 例子:只要请求接口中带有 "/react/api" ,就将将线上跨域接口http://www.dell-lee.com/react/api/header.json 转发到本地 loacalhost 服务下。实现跨域。
        配置: webpack.config.js
        devserver:{
          proxy: {
              "/react/api":{
                  target: "http://www.dell-lee.com",
                  source: false, //  将不接受在HTTPS上运行且具有无效证书的后端服务器。将source:false,可代理https 接口。
                  // 如果请求路径为html,则返回index.html文件
                  pathRewrite: {  // 重写路径,如遇到 请求路径中有 ’header.json‘,则返回'demo.json'路径下数据
                      'header.json': 'demo.json'
                  },
                  changeOrigin: true, // 爬虫限制 ,突破限制orgin 权限,支持访问,建议写入配置
                  bypass: function(req, res, proxyOptions) { // 拦截
                      if (req.headers.accept.indexOf('html') !== -1) {
                          console.log('Skipping proxy for browser request.');
                          return '/index.html';
                      }
                  }
              }
          }
        }
      ② 如果要将多个特定路径代理到同一目标
        devserver:{
          proxy: [{
            content:  ['/auth', '/api'],
            target: 'http://localhost:3000',
          }
        }

5.5 节 WebpackDevServer解决单页面路由404问题

      index.html可能必须提供该页面以代替任何404回复。devServer.historyApiFallback默认情况下禁用。通过传递启用它:
      devServer: {
          historyApiFallback: true
      }
      // 跟多配置参考:https://github.com/bripkens/connect-history-api-fallback

5.6 Eslint在webpack中配置 Eslint控制团队项目,代码中书写规范统一。 安装ESLINT: npm i eslint --save -dev

5.8-5.9 节 webpack打包优化

  1. 跟上技术迭代,升级webpack node npm 等版本
  2. 在尽可能杀跌模块少应用loader
     配置  exclude: /node_modules/, node-module 文件下不用loader编译,增加打包速度
          include: path.relative(__dirname, 'src'), src 文件下进行loader编译
     {
            test: /\.js$/,
            exclude: /node_modules/,
            include: path.relative(__dirname, 'src'),
            use: [
                { loader: "babel-loader" }
            ]

     }
     图片不需要对loader进行限制,因为图片都需要loader转化打包进项目中
  3. plugins 有效性
     如 new OptimizeCSSAssetsPlugin 对css文件压缩,dev环境下不需要使用,提高dev环境下打包速度。
     使用webpack官方提供的插件,确保每个插件可靠性。
  4. resolve
    resolve: {
        extensions: ['.js','.jsx'],
        mainFiles: ['index', 'child'],
        alias: {
            'src': path.resolve(__dirname, '../src')
        }
    }
    extensions: 可以让你import模块的时候不写格式,当你不写格式的时候,webpack会默认通过extensions中的格式去相应的文件夹中找
    alias:当你import的路径很长的时候,最好使用别名,能简化你的路径。
    设置别名:
    mainFiles: ['index', 'child'], 解析目录时,如 import child from '../src/'; 没有文件名称,则默认查找 index.js 文件
    resolve: {
        alias: {
            '@c': path.resolve(__dirname, '../src/a/b/c')
        }
    }
    这样你的import导入代码就可以改成import index.js from '@c/index.js'
    
5.10-5.11 节 webpack打包优化 (dllPlugin插件)t提升webpack打包速率
    描述:每次打包都需要重新打包引入的第三方库,是打包时间长,文件大,为了解决这个问题,
    我们将第三方库打包到vendor中,通过Dllplugin插件生成动态库连接文件,然后生成第三包映射关系文件
    mainfest.json文件。在通过DllReferencePlugin ,将mainfest.json引入,使我们能顺利使用被
    编辑打包后的第三方包。
    1. 创建webpack.congfig.dll.js文件
        const path = require('path')
        const webpack = require('webpack')

        module.exports = {
            mode: 'production',
            entry: {
                vendor: ['jquery', 'lodash'] // 要打包进vendor的第三方库
            },
            output: {
                filename: '[name].dll.js', // 打包后的文件名
                path: path.resolve(__dirname, '../dll'), // 打包后存储的位置
                library: '[name]_[hash]' // 挂载到全局变量的变量名,这里要注意 这里的library一定要与DllPlugin中的name一致
            },
            plugins: [
                new webpack.DllPlugin({ // 用于打包出一个个单独的动态链接库文件
                    name: '[name]_[hash]', // 引用output打包出的模块变量名,切记这里必须与output.library一致
                    path: path.join(__dirname, '../dll', '[name].manifest.json') // 描述动态链接库的 manifest.json 文件输出时的文件名称
                })
            ]
        }
        //  package.json 
        "build:dll": "webpack --config ./build/webpack.dll.config.js",
         执行: npm run build:dll
        2. 将映射文件mainfest.json文件引入  // webpack.config.js
            new webpack.DllReferencePlugin({
              manifest: require('./dll/vendor.manifest.json')
            }),
            注意:mainfest映射文件,可以让webpack打包时查看是否打包第三方模块包,如果没打就使用node-module中,如果有,使用打包好的第三方模块包。

        3. 动态生成script标签并引入 第三方包 // webpack.config.js
            new AddAssetHtmlPlugin({
                filepath: path.resolve(__dirname, '../dll/vendor.dll.js')
            })
            webpack会将dll打包出来的js文件通过script标签引入到index.html文件中
            如: <script type="text/javascript" src="vendor.dll.js"></script>第三方库
            执行: npm run build 查看打包速度。

    要求:如果需要引入多个第三方包,怎么优化?
        1. webpack.dll.congif.js中修改入口文件,添加第三方包
           entry: {
                vendor: ['lodash'], // 要打包进vendor的第三方库
                jquery: ['jquery']
            },
        2. weback.base.js 中动态添加映射文件,和第三方包引入插件
            // 拆分plugins插件。
            const plugins = [
                new HtmlWebpackPlugin({
                    template: 'src/index.html'
                }),
                new CleanWebpackPlugin(),
            ]
            //  获取dll文件夹下所有文件。
            const files = fs.readdirSync(path.resolve(__dirname, '../dll'));
            files.forEach(file => {
                 //  如果是dll.js结尾文件,使用AddAssetHtmlPlugin在html页面中使用script动态引入
                  if (/.*\.dll.js/.test(file)) {
                      plugins.push(new AddAssetHtmlPlugin({
                          filepath: path.resolve(__dirname, '../dll/', file)
                      }))
                  }
                 //  manifest.json结尾文件,使用DllReferencePlugin 添加mainfest映射文件。
                  if (/.*\.manifest.json/.test(file)) {
                      plugins.push(new webpack.DllReferencePlugin({
                          manifest: path.resolve(__dirname, '../dll', file)
                      }))
                  }
           })

5.12节 webpack 性能优化

    1. 控制包文件大小 ,tree-shaking 等
    2. thread-loader parallel-webpack(多页面多进程打包) happypack等多进程打包
    3. 合理使用sourceMap
    4. 结合stats分析打包结果,借助线上或者本地打包分析工具
    5. 开发环境内存编译 ,开发环境的时候不会生成dist文件夹,会直接从内存中读取,因为内存读取比硬盘读取快
    6. 开发环境无用插件剔除

5.13节 多页面打包

  基础版多页打包配置如何?
  // webpack.config.js
      // 增加入口文件
      entry: {
          index: './src/index.js',
          main: './src/main.js',
      },

      // 根绝每个如文件,配置并生成html页面
      const plugins = [
          new HtmlWebpackPlugin({
              template: 'src/index.html',
              filename: 'index.html',
              chunks: ['runtime', 'vendors', 'index', 'styles']   // 添加模块,如splitChunks拆分出的vender模块
          }),
          new HtmlWebpackPlugin({
              template: 'src/index.html',
              filename: 'main.html',
              chunks: ['runtime', 'vendors', 'main', 'styles']
          }),
          new CleanWebpackPlugin(),
      ]
      
  // 多页动态配置,并打包?
    const pluginsChange = (configs) => {
    const plugins = [
        new CleanWebpackPlugin(),
    ];
    Object.keys(configs.entry).forEach(item => {
          plugins.push(
              new HtmlWebpackPlugin({
                  template: `src/index.html`,
                  filename: `${item}.html`,
                  chunks: ['runtime', 'vendors', 'index', 'styles']
              })
          )
      })
      return plugins;
    }
    configs.plugins = pluginsChange(config);
    // configs 是webpack配置项
    module.exports = configs;

js 压缩插件uglifyjs-webpack-plugin

https: //segmentfault.com/a/1190000019182473 webpack笔记