前端进阶之旅前端进阶之旅
基础篇
进阶篇
高频篇
精选篇
手写篇
原理篇
面经篇
AI 面试
自检篇
每日一题
  • 综合
    • 综合题型
    • 其他问题
    • 设计模式
    • 思维导图
    • 学习路线
  • 前端基础
    • HTTP
    • 浏览器
    • 计算机基础
  • 进阶学习
    • NPM工作流
    • Docker
    • Canvas
    • Node学习指南
    • 前端综合文章
  • 其他
    • Handbook
    • 职场话题
    • CSS可视化
小程序题库
公众号动态
博客动态
开发者导航
基础篇
进阶篇
高频篇
精选篇
手写篇
原理篇
面经篇
AI 面试
自检篇
每日一题
  • 综合
    • 综合题型
    • 其他问题
    • 设计模式
    • 思维导图
    • 学习路线
  • 前端基础
    • HTTP
    • 浏览器
    • 计算机基础
  • 进阶学习
    • NPM工作流
    • Docker
    • Canvas
    • Node学习指南
    • 前端综合文章
  • 其他
    • Handbook
    • 职场话题
    • CSS可视化
小程序题库
公众号动态
博客动态
开发者导航

webpack回顾篇

首页2018-11-21 17:40:08Front-End
Webpack优化

基于webpack3

# 一、webpack简介

# 1.1 版本更迭

大版本变化

# 1.2 功能进化

Webpack V1

  • 编译、打包
  • HMR (模块热更新)
  • 代码分割
  • 文件处理

Webpack V2

  • Tree Shaking
  • ES module
  • 动态 Import
  • 新的文档

Webpack V3

  • Scope Hoisting (作用域提升)
  • Magic Comments (配合动态import使用)

版本迁移

V1 -> V2

迁移指南 https://doc.webpack-china.org/guides/migrating/

V2 -> V3

更新升级即可

# 二、webpack核心概念

# 2.1 Entry

  • 代码的入口
  • 打包的入口
  • 单个或多个

写法建议使用键值对写法

module.exports = {
  entry: 'index.js'
}
@前端进阶之旅: 代码已经复制到剪贴板
module.exports = {
  entry: '[index.js','vendor.js']
}
@前端进阶之旅: 代码已经复制到剪贴板
module.exports = {
  entry: {
      index:'index.js'
  }
}
@前端进阶之旅: 代码已经复制到剪贴板
module.exports = {
  entry: {
      index:['index.js','app.js'],
      vendor: 'vendor.js'
  }
}
@前端进阶之旅: 代码已经复制到剪贴板

# 2.2 Output

  • 打包成的文件(bundle)
  • 一个或多个
  • 自定义规则
  • 配合CDN
module.exports = {
  entry: 'index.js',
  output: {
      filename: 'index.min.js'
  }
}
@前端进阶之旅: 代码已经复制到剪贴板
module.exports = {
  entry: {
    index: 'index.js',
    vendor: 'vendor.js'
  },
  output: {
      filename: '[name].min[hash:5].js'
  }
}
@前端进阶之旅: 代码已经复制到剪贴板

# 2.3 Loaders

  • 处理文件
  • 转化为模块
module.exports = {
  module: {
      rules: [
        {
            test: /\.css$/,
            use: 'css-loader'
        }
      ]
  }
}
@前端进阶之旅: 代码已经复制到剪贴板

# 2.3.1 常用Loader

编译相关

  • babel-loader
  • ts-loader

样式相关

  • style-loader
  • css-loader
  • less-loader
  • postcss-loader

文件相关

  • file-loader
  • url-loader

# 2.4 Plugins

  • 参与打包整个过程
  • 打包优化和压缩
  • 配置编译时的变量
  • 极其灵活
module.exports = {
 plugins: [
    new webpack.optimize.UglifyJsPlugin()
 ]
}
@前端进阶之旅: 代码已经复制到剪贴板

# 2.4.1 常用plugins

优化相关

  • CommonsChunkPlugin
  • UglifyJsWebpackPlugin

功能相关

  • ExtractTextWebpackPlugin 提取css
  • HtmlWebpackPlugin 生成HTML模板
  • HotModuleReplacementPlugin 热模块替换
  • CopyWebpackPlugin 拷贝文件

# 2.5 名词

  • Chunk 打包过程分割的代码块
  • Bundle 打包后的文件
  • Module

# 三、初探 webpack

# 3.1 使用babel打包es6

# 3.1.1 编译 ES 6/7

Babel

npm install babel-loader@8.0.0-beta.0 @babel/core
npm install –save-dev babel-loader babel-core 
@前端进阶之旅: 代码已经复制到剪贴板

Babel Presets

主要有几种类型选择

  • es2015
  • es2016
  • es2017
  • env
  • babel-preset-react
  • babel-preset-stage 0 - 3
npm install @babel/preset-env –save-dev
npm install babel-preset-env –save-dev
@前端进阶之旅: 代码已经复制到剪贴板

Babel Polyfill

针对一些不能处理的函数方法(Generator、Set、Map、Array.from...)需要用到babel-Polyfill处理

  • 全局垫片
  • 为应用准备
npm install babel-polyfill –save
@前端进阶之旅: 代码已经复制到剪贴板
import “babel-polyfill”
@前端进阶之旅: 代码已经复制到剪贴板

Babel Runtime Transform

  • 局部垫片
  • 为开发框架准备
npm install babel-plugin-transform-runtime –save-dev

npm install babel-runtime –save
@前端进阶之旅: 代码已经复制到剪贴板

例子

module.exports = {
    entry: {
       app: 'app.js'
    },
    output: {
        filename: '[name].[hash:8].js'
    },
    module: {
        rules:[
            test: /\.js$/,
            use: {
                loader: 'babel-loader',
                options: {
                    presets: [
                        '@babel/preset-env',{
                            //指定target为根据哪些语法编译
                            targets: {
                                browsers: ['> 1%','last 2 versions']
                            }
                        }
                    ]
                }
            },
            exclude: '/node_modules'
        ]
    }
}
@前端进阶之旅: 代码已经复制到剪贴板

对于webpack中babel的配置可以单独提取处理.babelrc统一管理

{
    "presets": [
        ["@babel/preset-env",{
            targets: {
                browsers: ['> 1%','last 2 versions']
            }
        }]
    ],
    "plugins": [
      "transform-runtime"
    ]
]
@前端进阶之旅: 代码已经复制到剪贴板

# 3.2 打包 Typescript

npm i typescipt ts-loader  --save-dev
npm i typescipt awesome-typescript-loader  --save-dev
@前端进阶之旅: 代码已经复制到剪贴板

配置

  • tsconfig.json
  • webpack.config.js

tsconfig

  • 配置选项:官网/docs/handbook/compiler-options.html
  • 常用选项 compilerOptions include exclude

声明文件

用于编译时检查错误

以loadsh为例,需要安装@types/lodash带有声明文件的,而不是安装lodash

npm install @types/lodash
npm install @types/vue
@前端进阶之旅: 代码已经复制到剪贴板

Typings

也可以这样安装带有type的包

npm install typings
typings install lodash
@前端进阶之旅: 代码已经复制到剪贴板

例子

module.exports = {
    entry: {
        'app': 'app.js'
    },
    output: {
        filename: '[name].bundle.js'
    },
    module: {
        rules: [
            test: /\.tsx?$/,
            use: {
                loader: 'ts-loader'
            }
        ]
    }
}
@前端进阶之旅: 代码已经复制到剪贴板

在项目根目录创建tsconfig.json

 {
    "compilerOptions": {
         "module": "comonjs",
         "target": "es5", //编译后的文件在哪个环境运行
         "allowJs": true,//允许js语法
    },
    "include": [
        //编译路径
        "./src/*"
    ],
    "exclude": [
        //排除编译文件
        "./node_modules"
    ]
 }
@前端进阶之旅: 代码已经复制到剪贴板

# 3.3 提取 js 的公用代码

  • 减少代码冗余
  • 提高加载速度

主要使用内置插件实现webpack.optimize.CommonsChunkPlugin

{
	plugins: [
	     new webpack.optimize.CommonsChunkPlugin(option)
	]
}
@前端进阶之旅: 代码已经复制到剪贴板

例子

module.exports = {
    entry: {
        "pageA": "./src/pageA",
        "pageB": "./src/pageB",
        "vendor": ['loash']//业务代码和第三方代码区分开,给loash单独打一个包
    },
    output: {
        path: path.resolve(__dirname, './dist'),
        filename: '[name].bundle.js',
        chunkFilename: '[name].chunk.js'
    },
    plugins: [
    // 提取common
    new webpack.optimize.CommonsChunkPlugin({
         name: 'common',
         minChunks:2,//出现两次就打包成common代码
         chunks: ['pageA','pageB']//指定范围提取公共代码
     })
        
    // 提取vendor、取业务代码manifest
     new webpack.optimize.CommonsChunkPlugin({
         //把entry的vendor代码和这里的common(webpack打包的)代码合并
         names: ['vendor','manifest']
         minChunks: Infinity
     })
     // ==== 提取业务代码manifest== 合并到上面names中
     // 如果不想把webpack打包的代码和vendor代码合并 需要提取到manifest
     //new webpack.optimize.CommonsChunkPlugin({
         // webpack代码和vendordiam区分开
       //  name: 'manifest' //manifest即生成
       //  minChunks: Infinity
    // })
     
    ]
}
@前端进阶之旅: 代码已经复制到剪贴板

# 3.4 代码分割和懒加载

第一种方式:通过wepack内置方法

require.ensure动态加载一个模块,接收四个参数

  • []:dependencies 初次并不会执行
  • callback的时候才会执行
  • errorCallback 可省略
  • chunkName

第二种方式:通过ES2015 Loader Spec

System.import()后面演变为import()来动态加载模块

import()方式返回一个promise在import中传入需要依赖的明,动态加载模块,就可以像使用Promise一样使用import().then()

代码分割场景

  • 分离业务代码 和 第三方依赖
  • 分离业务代码 和 业务公共代码 和 第三方依赖
  • 分离首次加载 和 访问后加载的代码

例子

目标是提取pageA、pageB中公共的模块moduleA

运行打包这时loadash提取到vendor中

这时候还不是我们想要的

这时候这有pageA中才有moduleA

新建一个html验证是否动态加载

import()动态加载的写法

合并了subPageA和subPageB

引入css

例子

例子

例子

fe
  • 一、webpack简介
    • 1.1 版本更迭
    • 1.2 功能进化
  • 二、webpack核心概念
    • 2.1 Entry
    • 2.2 Output
    • 2.3 Loaders
      • 2.3.1 常用Loader
    • 2.4 Plugins
      • 2.4.1 常用plugins
    • 2.5 名词
  • 三、初探 webpack
    • 3.1 使用babel打包es6
      • 3.1.1 编译 ES 6/7
    • 3.2 打包 Typescript
    • 3.3 提取 js 的公用代码
    • 3.4 代码分割和懒加载
    • 3.5 处理 CSS 和 CSS 模块化
    • 3.6 PostCSS in Webpack
    • 3.7 Tree shaking
      • 3.7.1 JS Tree shaking
      • 3.7.2 CSS Tree shaking
  • 四、由浅入深Webpack
    • 4.1 文件处理
      • 4.1.1 图片处理
      • 4.1.2 处理雪碧图、base64、压缩图片
      • 4.1.2 处理字体文件
      • 4.1.3 处理第三方 JS 库
    • 4.2 HTML in webpack(自动生成HTML)
      • 4.2.1 生成 HTML
      • 4.2.2 HTML 中引入图片
      • 4.2.3 配合优化
  • 五、Webpack 环境配置
    • 5.1 Webpack Watch Mode
    • 5.2 Webpack Dev Server
      • 5.2.1 Dev Server
      • 5.2.2 proxy代理远程接口
      • 5.2.3 模块热更新
      • 5.2.4 开启调试SourceMap
      • 5.2.5 设置 ESLint 检查代码格式
      • 5.2.6 区分开发环境 和 生产环境
    • 5.3 使用 middleware 来搭建开发环境
  • 六、webpack实战场景
    • 6.1 分析打包结果
    • 6.2 优化打包速度
      • 6.2.1 方法一:分开vendor和app
      • 6.2.2 方法二:UglifyJsPlugin并行处理
      • 6.2.3 方法三:happyPack
      • 6.2.4 方法四:较少babel-loader编译时间
      • 6.2.5 其他
    • 6.3 长缓存优化
    • 6.4 多页面应用
      • 6.4.1 多页面特点
      • 6.4.2 多页面多配置
      • 6.4.3 多页面单配置
  • 七、更多学习

← eslint配置文件详解webpack常用插件总结篇 →