webpack初识
# webpack初识
# 打包工具的分类
仅介绍 4 款主流的打包工具:
grunt,gulp,webpack,rollup,以发布时间为顺序。
Grunt:最老牌的打包工具,它运用配置的思想来写打包脚本,一切皆配置,所以会出现比较多的配置项,诸如option,src,dest等等。而且不同的插件可能会有自己扩展字段,认知成本高,运用的时候需要明白各种插件的配置规则。Gulp:用代码方式来写打包脚本,并且代码采用流式的写法,只抽象出了gulp.src,gulp.pipe,gulp.dest,gulp.watch接口,运用相当简单。更易于学习和使用,使用gulp的代码量能比grunt少一半左右。(PS:此介绍的是gulp3,在gulp4不可用)Webpack: 是模块化管理工具和打包工具。通过 loader 的转换,任何形式的资源都可以视作模块,比如 CommonJs 模块、AMD 模块、ES6 模块、CSS、图片等。它可以将许多松散的模块按照依赖和规则打包成符合生产环境部署的前端资源。还可以将按需加载的模块进行代码分隔,等到实际需要的时候再异步加载。它定位是模块打包器,而 Gulp/Grunt 属于构建工具。Webpack 可以代替 Gulp/Grunt 的一些功能,但不是一个职能的工具,可以配合使用。Rollup:下一代 ES6 模块化工具,最大的亮点是利用 ES6 模块设计,利用tree-shaking生成更简洁、更简单的代码。一般而言,对于应用使用 Webpack,对于类库使用 Rollup;需要代码拆分(Code Splitting),或者很多静态资源需要处理,再或者构建的项目需要引入很多 CommonJS 模块的依赖时,使用 webpack。代码库是基于 ES6 模块,而且希望代码能够被其他人直接使用,使用 Rollup。
使用总结
Grunt:MPA,老牌打包工具,基于文件为媒介(运行慢,零散的脚本文件一当多起来就受到影响Gulp:MPA,易学,基于 nodejs 的 steam 流打包Webpack:SPA,目前最强大的打包工具,但是过于臃肿,如何单纯打包js不推荐Roleup:MPA,tree-shaking特性(针对es6,按需打包,多余的不要,目前(2018,vuex,react主流使用)
# 打包的概念
将一个或多个资源进行打包合成一个或多个包Bundle,在打包的构成中对资源进行处理,比如进行图片的压缩,将scss转化为css, 将ES6的语法转化为ES5的语法,将TypeScript转化为JavaScript的等操作。
webpack是什么?
前端模块化打包工具。依赖Node环境。
Q1:打包的操作Webpack, grunt和gulp的区别?
Grunt/glup 更强调的是前端流程的自动化,模块化不是它的核心。
Webpack 更强调的是模块化开发管理, 而文件压缩和预处理等功能是它的附加功能。
Q2: webpack 打包原理
webpack 打包原理是根据文件之间的依赖关系对其进行静态分析,然后将这些模块按照指定的规则生成静态资源,当webpack处理程序时,它会递归构建一个依赖关系图(dependency graph),其中包含应用程序需要的每一个模块,然后将所有的这些模块打包成一个或多bundle文件。
webpack使用识别入口文件,识别你的模块依赖,来打包你的代码。
至于你的代码是使用commonjs,amd,es6的import。webpack都会对其进行分析来获取代码的依赖。
做的是分析代码,转换代码,编译代码,输出代码。是基于commonJS编写的。
注意: 版本的配置很重要!importment
//打包 到dist包中
webpack ./src/main.js .dist/bundle.js
//webpack 4.x以上 加 -o
npx webpack ./src/main.js -o ./dist/bundle.js --mode development
2
3
4
5
// 使用webpack 配置文件打包
webpack --config webpack.conf.js (指定webpack的配置文件)
2
# webpack的配置
webpack.config.js 的创建和配置
// npm init; npm install
const path = require('path')
module.exports = {
entry: './src/main.js',
output: {
// 动态路径 绝对路径
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js'
}
}
2
3
4
5
6
7
8
9
10
11
// webpack 打包
webpack / npx webpack
2
npm 映射
//package.json
{
"name": "meetwebpack",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build": "webpack" // 做了一层映射
},
"author": "",
"license": "ISC"
}
2
3
4
5
6
7
8
9
10
11
12
13
// webpack打包 => npm指令打包
npm run build
// 优先运行本地的webpack 再运行全局的webpack
// 执行顺序:node_modules/.bins/... => 全局
2
3
4
开发式依赖
运行式依赖
// 全局安装webpack
npm install webpack@3.6.0 -g
// 局部安装webpack
npm install webpack@3.6.0 --save-dev/npm install webpack@3.6.0 -D
2
3
4
注意:在终端中输入的命令优先在全局中找webpack
# Tree-Shaking
有效的将在最终打包的文件中未使用的模块进行删除,以达到控制文件的大小
一个副作用是:有一些代码,是在
import时执行了一些行为,这些行为不一定和任何导出相关。
这就导致了一个很尴尬的问题,esm和cjs如何交互呢。这分为如下几种情况
- esm 导入cjs
- cjs 导入esm
- dynamic import 导入 esm
- dynamic import 导入 cjs
随着因为esm的存在多种导入和导出方式,这就导致情况更加复杂。而且不同的平台的处理方式不同,不同工具生成的代码之间又如何处理导入和导出。
这进一步导致了不同平台生成的代码要如何交互,rollup, webpack, babel, typescript,浏览器,node这几种工具要怎么处理cjs和esm的交互性呢。简直一大深坑。
# 最佳实践:
- 就是在前端代码中禁止使用commonJS
- 导出, 对单个字面量,变量,function, class 导出使用export
- 导入,对于export default的导出,使用import xxx from,对于named export的导出使用import * as lib from './lib' 和 import “{ a,b,c}" from './lib'
# 代码迁移
自动化迁移工具5to6-codemod (opens new window)
可以先通过exports和cjs transform将module.exports和require转换为export和import,接着可以通过named-export-generation将export default 进行转换
为了进一步防止新代码使用错误的方式,我们可以通过eslint进行禁止。通过eslint-plugin-import可以对模块的用法进行精细的控制,对应上面规则,我们开启如下规则
"import/no-anonymous-default-export": ["error", {
"allowArrowFunction": true,
"allowAnonymousClass": true,
"allowAnonymousFunction": true,
"allowLiteral": true,
"allowObject": false,
"allowArray": true
}]
2
3
4
5
6
7
8
官网:https://www.webpackjs.com/ (opens new window) 文档:https://www.webpackjs.com/concepts/ (opens new window)