Rollup也是一款ESModule打包器,可以将项目中的细小模块打包成整块代码,使得划分的模块可以更好的运行在浏览器环境或者是Nodejs环境。Rollup与Webpack作用非常类似,不过Rollup更为小巧。webpack结合插件可以完成前端工程化的绝大多数工作,而Rollup仅仅是一款ESM打包器,没有其他功能,例如Rollup中并不支持类似HMR这种高级特性。Rollup并不是要与Webpack全面竞争,而是提供一个充分利用ESM各项特性的高效打包器。
mkdir/test/src
yarn add rollup --dev
yarn rollup ./src/index.js --format iife --file dist/bundle.js
index.js
// 导入模块成员
import { log } from './logger'
import messages from './message'
// 使用模块成员
const msg = messages.hi
log(msg)
logger.js
export const log = msg => {
console.log('---------- INFO ----------')
console.log(msg)
console.log('--------------------------')
}
export const error = msg => {
console.error('---------- ERROR ----------')
console.error(msg)
console.error('---------------------------')
}
message.js
export default {
hi: 'Hey Guys, I am jal '
}
打包结果:
/dist/bundle.js
(function () {
'use strict';
const log = msg => {
console.log('---------- INFO ----------');
console.log(msg);
console.log('--------------------------');
};
var messages = {
hi: 'Hey Guys, I am jal '
};
// 导入模块成员
// 使用模块成员
const msg = messages.hi;
log(msg);
}());
可以发现打包结果很简洁。因为:Rollup
默认会开启TreeShaking
优化输出结果。
执行:yarn rollup --config
或者: yarn rollup --config rollup.config.js
export default {
input: './src/index.js',
output: {
file: 'dist/bundle.js',
format: 'iife' // 打包格式
}
}
Rollup自身的功能就是对ESM进行合并打包,如果需要更高级的功能,如加载其他类型资源模块,导入CommonJS模块,编译ES新特性,Rollup支持使用插件的方式扩展实现,插件是Rollup唯一的扩展方式。
1.通过导入json
文件学习如何使用Rollup
插件。
2.安装插件rollup-plugin-json
, 运行:yarn add rollup-plugin-json --dev
3.rollup.config.js
import json from 'rollup-plugin-json'
export default {
input: './src/index.js',
output: {
file: 'dist/bundle.js',
format: 'iife'
},
plugins: [
json()
]
}
修改 : ./src/index.js
import {log} from './logger'
import messages from './message'
import {name, version} from '../package.json'
const msg = messages.hi
log(msg)
log(name)
log(version)
查看打包结果:
(function () {
'use strict';
const log = msg => {
console.log('---------- INFO ----------');
console.log(msg);
console.log('--------------------------');
};
var messages = {
hi: 'Hey Guys, I am jal '
};
var name = "test";
var version = "1.0.0";
// 导入模块成员
// 使用模块成员
const msg = messages.hi;
log(msg);
log(name);
log(version);
}());
可以发现json
中用到的属性被打包进来了,没用到的属性被TreeShaking
移除掉了。
Rollup
不能像webpack
那样通过模块名称加载npm
模块,为了抹平差异,Rollup
官方提供了一个插件rollup-plugin-node-resolve
,通过这个插件,就可以在代码中直接使用模块名称导入模块。
安装插件:yarn add rollup-plugin-node-resolve --dev
修改rollup.config.js
import json from 'rollup-plugin-json'
import resolve from 'rollup-plugin-node-resolve'
export default {
input: './src/index.js',
output: {
file: 'dist/bundle.js',
format: 'iife'
},
plugins: [
json(),
resolve()
]
}
修改./src/index.js
import _ from 'lodash-es' // lodash模块的ESM版本
import {log} from './logger'
import messages from './message'
import {name, version} from '../package.json'
const msg = messages.hi
log(msg)
log(name)
log(version)
log(_.camelCase('hello world'))
执行 yarn rollup --config
.可以发现lodash
被打包进去了。
安装插件: yarn add rollup-plugin-commonjs
修改 rollup.config.js
import json from 'rollup-plugin-json'
import resolve from 'rollup-plugin-node-resolve'
import commonjs from 'rollup-plugin-commonjs'
export default {
input: './src/index.js',
output: {
file: 'dist/bundle.js',
format: 'iife'
},
plugins: [
json(),
resolve(),
commonjs()
]
}
使用动态导入的方式实现模块的按需加载,Rollup
内部会自动去处理代码的拆分,也就是分包。
rollup.config.js
import json from 'rollup-plugin-json'
import resolve from 'rollup-plugin-node-resolve'
import commonjs from 'rollup-plugin-commonjs'
export default {
input: './src/index.js',
output: {
// file: 'dist/bundle.js',
// format: 'iife',
dir: 'dist',
format: 'amd'
},
plugins: [
json(),
resolve(),
commonjs()
]
}
修改: ./src/index.js
import('./logger').then(({ log }) => {
log('code splitting~')
})
执行yarn rollup --config
查看打包结果
rollup.config.js
export default {
// input: './src/index.js',
// input: ['src/index.js', 'src/album.js'], // 多入口打包
input: { // 这种写法也可以进行多入口打包
foo: 'src/index.js',
bar: 'src/album.js'
},
output: {
dir: 'dist', // 动态导入时会分包成多文件
format: 'amd' // 动态导入不支持iife
},
}
注意此时生成的js文件就要以AMD标准的require方式引入
新建文件/dist/index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<!-- AMD 标准格式的输出 bundle 不能直接引用 -->
<!-- <script src="foo.js"></script> -->
<!-- 需要 Require.js 这样的库 -->
<script src="https://unpkg.com/requirejs@2.3.6/require.js" data-main="foo.js"></script>
</body>
</html>
(1) Rollup优势
如果我们正在开发应用程序,需要引入大量的第三方库,代码量又大,需要分包打包,Rollup的作用则会比较欠缺。
如果我们正在开发一个框架或者类库,Rollup的这些优点则非常有必要,缺点则可以忽略。所以大多数知名框架/库都在使用Rollup作为模块打包器。
总结:Webpack大而全,Rollup小而美。
选择标准:
yarn init yes
安装Parcel:yarn add parcel-bundler --dev
./src/index.html Parcel中的入口文件是HTML文件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Parcel Test</title>
</head>
<body>
<script src="./main.js"></script>
</body>
</html>
./src/main.js
// import $ from 'jquery' // 自动安装依赖
import foo from './foo'
import './style.css'
import img from './1.png'
foo.bar()
// 动态导入,自动拆分模块
import('jquery').then($=>{
$(document.body).append('<h1>Hello</h1>')
$(document.body).append(`<img src="${img}" />`)
})
if(module.hot) {
module.hot.accept(() => {
console.log('hmr') // 模块热替换
})
}
./src/foo.js
export default {
bar: () => {
console.log('foo jal111 ..')
}
}
./src/style.css
body {
background-color: pink;
}
./src/1.png
执行命令:yarn parcel src/index.html
会自动启动一个http
服务,并且监听文件的变化,自动开启了模块热替换功能,依赖文件也是自动安装,整个过程都是零配置。
如何以生产模式进行打包:yarn parcel build src/index.html
对于相同体量的项目进行打包,Parcel
会比Webpack
快很多,因为在Parcel
内部使用的是多进程同时去工作,充分发挥了多核CPU的性能,而Webpack中可以使用happypack
插件实现这一点。
Parcel
首个版本发布于2017年,当时Webpack
使用上过于繁琐。Parcel
真正意义上实现了完全零配置,而且Parcel构建速度更快。
而现在大多数项目还是使用Webpack作为打包器,可能是因为Webpack
有更好的生态、Webpack
越来越好用.
1.软件开发需要多个人协同
2.不同开发者具有不同的编码习惯和喜好
3.不通的喜好增加项目维护成本
4.每个项目或者团队需要明确统一的标准
1.代码,文档,甚至是提交日志
2.开发过程中人为编写的成果图
3.代码标准化规范最为重要
1.编写前人为的标准约定
2.通过工具实现lint
1.eslint工具使用
2.定制eslint校验规则
3.eslint对TypeScript的支持。
4.eslint结合自动化工具或者webpack
4.基于eslint的衍生工具
5.StyleLint工具的使用
.eslintrc.js
module.exports = {
// 设置运行的环境,决定了有哪些默认全局变量
env: {
browser: true,
node: true,
es6: true,
jquery: true,
es2020: true
},
// eslint 继承的共享配置
extends: [
'standard'
],
// 设置语法解析器,控制是否允许使用某个版本的语法
parserOptions: {
ecmaVersion: 11
},
// 控制某个校验规则的开启和关闭
rules: {
'no-alert': 'error'
},
// 添加自定义的全局变量
globals: {
"$": 'readonly',
}
}
将配置写在代码的注释中,然后再对代码进行校验
const str1 = "${name} is coder" // eslint-disable-line no-template-curly-in-string
console.log(str1)
eslint通过loader形式校验JavaScript代码.
在打包js代码之前,校验js代码。
前置工作:
后续配置:
案例:普通的react应用
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: 'eslint-loader',
enforce: 'pre'
}
]
打包:npm build
配置react 中使用eslint
npm install eslint-plugin-react --save
.eslintrc.js
module.exports = {
rules: {
'react/jsx-uses-react': 2 // error: 2
},
plugins: [
'react'
]
}
在一些脚手架中其实已经继承了eslint,例如:vue-cli
vue create my-app
npx eslint --init
在安装的过程中会让选择是否使用typescript lint,选择yes即可。
完全可以参考eslint的使用方式
npm install stylelint --dev
npx stylelint ./index.css
npm install stylelint-config-standard stylelint-config-sass-guidelines --save-dev
.stylelintrc.js
module.exports = {
extends: [
"stylelint-config-standard",
"stylelint-config-sass-guidelines"
],
rules: [
]
}
运行:npx stylelint ./index.css
近两年流行的前端代码通用型格式化工具,几乎可以完成各种代码的格式化。通过Prettier可以完成前端的规范化操作。
例如:基本的html, css, scss,vue文件,jsx文件,.md文件等等。这些文件都可以通过Prettier格式化。
yarn add prettier --dev
安装prettier到当前项目
yarn prettier style.css
将格式化的结果输出到命令行
yarn prettier style.css --write
将格式化的结果覆盖原文件
yarn prettier . --write
对当前整个项目进行格式化
代码提交至仓库之前为执行lint工作
通过git hooks在代码提交之前强制lint
在一个Git
仓库中,进入.git/hooks
目录,然后看到很多sample文件,执行cp pre-commit.sample pre-commit
,拷贝了一份pre-commit文件出来,把里面的内容先去掉,就写一句简单的echo看看Git钩子的效果(第一行是可执行文件必须要有的固定语法,不可以删除)
pre-commit
#!/bin/sh
echo "git hooks"
然后回到仓库根目录,执行git add .,git commit -m"xx"
就可以看到输出了git hooks
,说明pre-commit
这个钩子已经生效了
husky可以实现Git Hooks的使用需求。在不编写脚本文件的情况下使用git hooks。
npm install husky --save-dev
package.json
{
"name": "GitHooks",
"version": "1.0.0",
"main": "index.js",
"author": "jiailing <517486222@qq.com>",
"license": "MIT",
"scripts": {
"test": "eslint ./index.js"
},
"devDependencies": {
"eslint": "^7.3.1",
"eslint-config-standard": "^14.1.1",
"eslint-plugin-import": "^2.21.2",
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-promise": "^4.2.1",
"eslint-plugin-standard": "^4.0.1",
"husky": "^4.2.5",
"lint-staged": "^10.2.10",
},
// 配置:husky
"husky": {
"hooks": {
"pre-commit": "yarn test", // 在commit提交之前的操作
}
}
}
然后执行
echo node_modules > .gitignore
git add .
git commit -m "husky"
可以看到我们的index.js的代码报错被输出到控制台了,并且Git commit
失败了。
说明husky
已经完成了在代码提交前的lint工作。不过husky并不能对代码进行格式化,此时可以使用lint-stage
yarn add lint-staged --dev
,对代码进行格式化。
lint-staged 配合husky达到一些其他的功能。
package.json
{
"name": "GitHooks",
"version": "1.0.0",
"main": "index.js",
"author": "jiailing <517486222@qq.com>",
"license": "MIT",
"scripts": {
+ "test": "eslint ./index.js",
+ "precommit": "lint-staged"
},
"devDependencies": {
"eslint": "^7.3.1",
"eslint-config-standard": "^14.1.1",
"eslint-plugin-import": "^2.21.2",
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-promise": "^4.2.1",
"eslint-plugin-standard": "^4.0.1",
"husky": "^4.2.5",
"lint-staged": "^10.2.11"
},
// 在代码commit 提交之前对代码进行拦截,如果不符合eslint则拒绝提交(强制验证代码)
+ "husky": {
+ "hooks": {
+ "pre-commit": "yarn precommit"
+ }
+ },
+ // 在commit之前强制对代码进行eslint
+ "lint-staged": {
+ "*.js": [
+ "eslint",
+ "git add"
+ ]
+ }
}