webpack
本节将学习webpack的
由来,核心概念以及使用。
更加详细的学习,参考至webpack中文网
由来
- 为什么需要webpack?
- 模块化开发: 浏览器无法识别模块,只能识别
三大件 - 依赖管理:
自动解析模块之间的依赖关系,并打包到一起。 - 代码压缩: 将模块打包为1个文件,并压缩以
减少体积。 - 兼容性: 不同浏览器对
某些特性的支持不同,可以处理兼容性 - 自动化构建: 手动构建过程繁琐,例如
热重载,自动实时编译更新。
总结: 简而言之,vue-react-angular及模块化开发的热门,导致了打包工具的存在非常有必要。
核心概念
介绍配置文件:
webpack.config.js的入口(entry),输出(output),转换(loader),插件(plugin)和模块(mode)
入口(entry)
配置构建
依赖图(bundle)的起点文件, 默认值是./src/index.js,
webpack会从该文件开始,找入口文件(直接或间接)的依赖。
// 支持在 webpack.config.js 手动修改
module.exports = {
entry: './index.js',
//单入口,常用,一般适用于单页面应用
entry: {
pageOne: './src/pageOne/index.js',
pageTwo: './src/pageTwo/index.js',
pageThree: './src/pageThree/index.js',
},
//多个入口,SSR, 一般适用于多页面应用
}输出(output)
配置输出
打包的文件路径,以及输出的文件名。
默认值: 路径./dist, 文件名main.js。 webpack会把打包好的文件(bundle),输出到指定的文件夹。
// 支持在webpack.config.js 手动修改
// 需要引入path,
// 配置output对象的path 和 filename 属性
const path = require('path');
module.exports = {
output:{
path: path.resolve(__dirname, 'dist'),
//当前路径下的dist
filename: 'my-first-webpack.bundle.js'
// 单入口:输出的文件名
filename: '[name].js',
// 多入口,使用[name]占位符,需保证每个文件有唯一的文件名。
}
}处理器(loader)
用于对
模块的源代码进行转换, 配置处理其他文件的能力。
webpack本身只具有import模块后,预处理js和json的能力,
配置loader使其预处理更多文件,将其转换为js或dataURL.
每个loader是module.rules里的每一项规则,由test和use组成.
# 例如处理css的css-loader 和 处理ts的ts-loader
npm i css-loader ts-loader --save-dev// 使用module.rules作为配置项, 配置loader
module.exports = {
module:{
// 规则数组
rules: [
// 每一个loader表示一个规则,都由test和use组成
{
test: /\.css$/, //匹配.css结尾的
use: 'css-loader'
},
{
test: /\.ts$/, //匹配.ts结尾的
use: 'ts-loader'
}
]
}
}插件(plugins)
插件是拓展webpack其他能力的模块或者js对象集合.
用于解决loader无法实现的其他功能.
插件是一个具有 apply 方法的 JavaScript 对象。
插件可以携带参数/选项,向plugins属性传入一个new 实例。
const HtmlWebpackPlugin = require('html-webpack-plugin');
const webpack = require('webpack'); // 访问内置的插件
module.exports = {
plugins: [
new HtmlWebpackPlugin(),
// HtmlWebpackPlugin 将生成一个 HTML 文件
new webpack.ProgressPlugin(),
// ProgressPlugin 用于自定义编译过程中的进度报告,
]
}模式(mode)
可以启用 webpack 内置在相应
环境下的优化。 指定development,production(默认)或者none
module.exports = {
mode: 'development'
}支持ES2015
ES2015 中的
import和export语句已经被标准化。 webpack 能够提供开箱即用般的支持.
// npm和nodejs只支持 const a = require('./a.js')
import { say } from './a.js'
// 而用webpack构建的话,支持ESM
export {
say
}
// module.exports = {
// say
// }webpack打包优化
具体从
webpack-bundle-analyzer插件查看依赖
到按需加载,resolve配置,代码压缩,sourceMap的角度。
webpack-bundle-analyzer插件
一个 plugin 和 CLI 工具,它将 bundle 内容
展示为一个便捷的、交互式、可缩放的树状图形式。不需要的或者体积较大的依赖包来进行针对性的优化。
- 普通项目,
插件使用
- 安装
npm i webpack-bundle-analyzer --save-dev- 引入插件
const BundleAnalyzer = require('webpack-bundle-analyzer')
// webpack.config.js
module.exports = {
plugins: [
// 配置插件
new BundleAnalyzer(), //使用默认配置
]
}- 运行查看
npm run build --report- 也支持
CLI使用,
具体查看插件官网 Options (for CLI)
- vue-cli2中:
内置webpack-bundle-analyzer
直接运行查看。
具体优化
按需加载
- 路由
懒加载,异步加载组件。 vue2和vue3都有对应的API. - 组件库引入方式:按需加载第三方组件或插件。
优化loader解析查找规则
优化webpack中loader的配置(rules)
- test: 优化正则表达式,减少文件查询时间
- loader: 开启cacheDirectory选项,开启缓存,
- 添加include, exclude, 指定或者排除无关文件
示例
// webpack.config.js
module.exports = {
// 通过rules配置所有的loader
rules: [
{
test: '/\.js$/',
loader: 'bable-loader?cacheDirectory', //在loader上,添加?cacheDirectory
include:[resolve('src')]
}
]
}优化文件路径 - resolve
resolve可以设置模块如何的规则
被查找和被解析
例如import 'lodash', 设置依次查找解析.js,.vue
- 优化webpack中的resolve的配置
- 配置别名,设置解析查找规则,加快查找模块的速度
- 配置extensions选项,配置解析规则
- 配置alias选项,配置别名
// webpack.config.js
module.exports = {
resolve:{
extensions: ['.js','.vue','.json'],
alias: {
'@': resolve('src')
}
}
}
// 配置完如上, 即可以在项目中引入和配置
import tool from '@/utils/tool'
// 会从src开始查找,仅查找.js, .vue, .json后缀代码压缩 - optimization
webpack开启
production模式时,会默认使用TerserPlugin插件,对代码压缩。
指定别的压缩插件(例如closure-webpack-plugin)
将它作为optimization.minimizer, 插件确保具有Tree-Shaking的能力.
tree-shaking:
- rollup提出的一种概念,具有
删除未引用代码(dead code)的能力
- rollup提出的一种概念,具有
通过配置
optimization中的minimizer选项,可以配置压缩插件
const ClosurePlugin = require('closure-webpack-plugin')
// 例如指定生产模式
module.exports = {
// mode: 'production',
// 例如使用ClosurePlugin插件压缩
optimization: {
minimizer: [
new ClosurePlugin()
/* 默认等价于如下配置
new ClosurePlugin({mode: 'STANDARD'}, {
// compiler flags here
//
// for debugging help, try these:
//
// formatting: 'PRETTY_PRINT'
// debug: true,
// renaming: false
})
*/
]
]
}
}关闭sourceMap - 生产环境
sourceMap是一种映射功能,可以将打包后的代码映射到原始位置。
便于开发时追踪到错误和警告。
- 如何开启source-map?
- 配置webpack中的
devtool
// webpack.cofig.js
module.exports = {
devtool: 'inline-source-map',
// 一般配合webpack-dev-server使用(见webpack官网)
// 指定serve路径
devServer: {
static: './dist',
}
}- 例如
/*
Uncaught ReferenceError: cosnole is not defined
at HTMLButtonElement.printMe (print.js:2)
*/- 如何关闭source-map?
- 配置webpack中的
devtool
module.exports = {
devtool: 'none'
}- vuecli中的sourceMap配置
- productionSourceMap
//vue.config.js
module.exports = {
productionSourceMap: false, //默认为true
// 如果你不需要生产环境的 source map,可以将其设置为 false 以加速生产环境构建。
}从零搭建一个vue-webpack模板
基于上面学习的
核心配置, 以及vue-loader的内容.
我们来练手从零搭建一个vue-webpack模板, 不使用vue-cli脚手架.
有关vue-loader的内容, 学习至vue-loader官网
初始化项目
初始化一个webpack项目
- 初始化package.json
npm init -y- 安装webpack,webpack-cli和html-webpack-plugin
npm i --save-dev webpack webpack-cli html-webpack-plugin
# 表示仅仅将webpack用于构建,打包上线时不使用
# webpack-cli是为了命令行可以使用webpack- 新建
webpack.config.js, 添加基础配置
const HtmlWebpackPlugin = require('html-webpack-plugin');
// 使用默认的入口src/index.js
// 使用默认出口./dist
// 配置空loader,plugins,环境为默认不配置
module.exports = {
module: {
rules: [
]
},
plugins: [
new HtmlWebpackPlugin()
],
}- 新建
src文件夹和index.js
import { say } from './a.js'
say()
console.log(123);- 新建
a.js
const say = function(){
console.log('aaaaaaa')
}
export {
say
}- 修改
package.json,确保是私有的
//"main": "index.js", 移除掉这行
"private": true,- 添加
build命令
"build": "webpack"- 运行测试
npm run build- 打包成功
// 多了1个dist文件夹, index.html和main.js
(()=>{"use strict";console.log("aaaaaaa"),console.log(123)})();安装和配置vue
主要是安装
vue,以及安装vue-loader和vue-template-compiler
注意:vue和vue-template-compiler版本号必须一致。
参考至:手动设置 ...待续
XDocs