在日常项目开发中构建东西是必不可少的,所以也是咱们需求掌握学习的一个重要部分,在技能蓬勃发展的今日,许多优秀的构建东西涌现出来,前端主流打包东西首要有 grunt,gulp,rollup,webpack,vite,parcel等
那么接下来咱们就介绍下比较常用的三个打包东西rollup,webpack,vite对比下这几个打包东西的优缺陷和适用场景
rollup—合适打包类库
Rollup 是一个 JavaScript 模块打包器,他所负责的作业只是把咱们写的代码转化为js
特色:原生支撑tree shaking(去除无用代码),支撑一起生成umd、commonjs,es的代码
缺陷:
- 模块过于静态化,HMR很难完结
- 仅面向ES module,无法可靠的处理
commonjs以及umd依靠
rollup根本装备
import resolve from 'rollup-plugin-node-resolve';// 供给解析import引进第三方依靠支撑(node_modules里的文件)
import commonjs from '@rollup/plugin-commonjs';//插件将它们转换为ES6版本
import postcss from 'rollup-plugin-postcss';
import image from '@rollup/plugin-image';
import babel from 'rollup-plugin-babel';//将代码转译为浏览器或许node支撑的语法,
import json from 'rollup-plugin-json'//引进该插件能够让源码中能够用import引进json文件
import serve from 'rollup-plugin-serve';//本地服务
import livereload from 'rollup-plugin-livereload';//热更新
const input = 'src/index.js'
export default {
input, // 打包进口//必填
external:[],//指出应该将哪些模块看做外部模块,不好咱们的源码包打在一起,该参数接纳数组或许参数为模块名称的函数,回来true则将被看做外部引进不打包在一起
output: [{ // 打包出口
file: 'dist/index.js', // 最终打包出来的文件途径和文件名,这里是在package.json的browser: 'dist/index.js'字段中装备的
format: 'umd', // 必填//umd是兼容amd/cjs/iife的通用打包格局,合适浏览器//不设置该选项导出代码无法履行(无法识别export)
name:'index',//导出的文件名称//必填
globals:{//设置全局变量?
jquery:"$"
}
},
{
file: input.replace('src/', 'dist/').replace('.js', '.cjs'),
format: 'cjs'
},{
file: input.replace('src/', 'dist/').replace('.js', '.mjs'),
format: 'esm'
}],
plugins: [ // 打包插件
postcss({
extensions: [ '.css' ],
}),
resolve(), // 查找和打包node_modules中的第三方模块
commonjs(), // 将 CommonJS 转换成 ES2015 模块供 Rollup 处理,用在其他插件转换源码之前,放置其他插件改动破坏CommonJS的检测
babel({
exclude: 'node_modules/**' // 只转译咱们的源代码
}),
image(),
json(),//让源码能够引进json 文件
// 热更新 默许监听根文件夹
livereload({watch:'dist'}),
// 本地服务器
serve({
open: true, // 主动翻开页面
port: 8000,
openPage: '/src/test.html', // 翻开的页面
contentBase: ''
})
]
};
webpack—合适打包项目
装备项杂乱,社区丰厚 在webpack项目中需求运用的静态资源,css,以及less等预处理器需求手动引进对应的loader才干运用, 支撑代码分割,热更新,丰厚的插件系统,经过运用loader能够解析各种类型的资源等
缺陷:冷发动,热更新随着项目体量增大而变慢,体量大的项目热更新一次甚至需求几分钟
webpack的底层原理 找到进口->形成文件之间的依靠关系树=>经过loader处理对应资源=>生成打包成果=>发动本地服务进行烘托=>浏览器恳求,整个包回来
在整个作业进程的每个环节都有预留钩子,插件能够在不同环节进行一些自定义使命
webpack原理图:
webpack根本装备
//webpack.base.config.js
const path = require('path')// 引进 path 模块
const CopyWebpackPlugin = require('copy-webpack-plugin')// 引进静态资源复制插件
const isProduction = process.env.NODE_ENV === 'production'// 判别当时环境是否是出产环境
const MiniCssExtractPlugin = require('mini-css-extract-plugin')// 样式独自别离到一个文件中
module.exports = {
// 打包进口地址
entry: {
// 因为可能是多页,所以采用对象的方式
index: ['./src/views/index/index.js']
},
// 模块resolve的规矩
resolve: {
//主动的扩展后缀,比如一个js文件,则引用时书写可不要写.js
extensions: ['.js', '.json', '.css', '.less'],
// 途径别号
alias: {
'@': path.join(__dirname, '../src')
}
},
// 构建目标
target: ['web', 'es5'],
// context 是 webpack entry 的上下文,是进口文件所处的目录的绝对途径,默许情况下是当时根目录。
// 因为咱们 webpack 装备文件放于 build 目录下,所以需求从头设置下 context ,使其指向根目录。
context: path.resolve(__dirname, '../'),
plugins: [
// 把public的一些静态文件复制到指定方位,扫除 html 文件
new CopyWebpackPlugin({
patterns: [
{
from: path.resolve(__dirname, '../public'),
globOptions: {
dot: true,
gitignore: false,
ignore: ['**/*.html']
}
}
]
})
],
module: { // 不同类型模块的处理规矩
rules: [// 处理 css、less 文件
{
test: /\.(css|less)$/,
use: [
isProduction ? MiniCssExtractPlugin.loader : 'style-loader',
{
loader: 'css-loader',
options: {
sourceMap: !isProduction, // 是否运用source-map
esModule: false// 兼容IE11
}
},
{
loader: 'postcss-loader',
options: {
sourceMap: !isProduction // 是否运用source-map
}
},
'less-loader'
]
},
{// 解析 html 中的 src 途径
test: /\.html$/,
use: 'html-loader'
},
{// 对图片资源文件进行处理,webpack5现已抛弃了url-loader,改为type
test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
type: 'asset',
exclude: [path.resolve(__dirname, 'src/assets/imgs')],
generator: {
filename: 'imgs/[name].[contenthash][ext]'
}
},
{// 对字体资源文件进行处理,webpack5现已抛弃了url-loader,改为type
test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
type: 'asset',
generator: {
filename: 'fonts/[name].[contenthash][ext]'
}
},
{// 对音频资源文件进行处理,webpack5现已抛弃了url-loader,改为type
test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
type: 'asset',
exclude: [path.resolve(__dirname, 'src/assets/medias')],
generator: {
filename: 'medias/[name].[contenthash][ext]'
}
},
{
test: /\.(m|j)s$/,
exclude: /node_modules/,
use: [
{
loader: 'babel-loader',
options: {
cacheDirectory: true
}
}
]
}
]
}
}
//webapck.dev.config.js
const { merge } = require('webpack-merge')// 引进合并对象插件
const path = require('path')// 引进 path 模块
const HtmlWebpackPlugin = require('html-webpack-plugin')// 引进打包html插件
const baseWebpackConfig = require('./webpack.base.config')// 引进基础装备文件
const devWebpackConfig = merge(baseWebpackConfig, {
// 模式,必填项
mode: 'development',
// 敞开持久化缓存
cache: {
type: 'filesystem',
buildDependencies: {
config: [__filename]
}
},
output: {
// 输出文件目录
path: path.resolve(__dirname, '../dist'),
// 输出文件名
filename: 'js/[name].js',
},
// 源码映射
devtool: 'eval-cheap-module-source-map',
// 开发服务装备
devServer: {
// 服务器 host,默以为 localhost
host: '0.0.0.0',
// 服务器端口号,默许 8080
port: 7001,
// 静态资源特点
static: {
// 挂载到服务器中间件的可访问虚拟地址
// 例如设置为 /static,在访问服务器静态文件时,就需求运用 /static 前缀
// 相当于webpack-dev-server@3.X的 contentBasePublicPath 特点
publicPath: './',
// 告知服务器从哪里供给内容
directory: path.join(__dirname, '../public')
},
// 需求监听的文件,因为是多页运用,无法完结热更新,所以都只能刷新页面
watchFiles: ['src/**/*']
},
// 插件
plugins: [
new HtmlWebpackPlugin({
template: './src/views/index/index.html',
favicon: path.resolve(__dirname, '../public/favicon.ico')
})
]
})
module.exports = devWebpackConfig
vite—合适打包项目
开箱即用 对于项目中需求的静态资源,html,less等无需手动引进loader来处理这些资源,直接引进对应的库即可
vite的底层原理 敞开web服务器=>浏览器恳求对应资源=>本地服务器编译对应文件=>编译成果回来给浏览器烘托;
vite原理图
发动服务器=> 恳求模块时按需动态编译显示;跟webpack相比开发环境的又是在项目大的时候优势就很明显了
开发环境:
根据esbuild进行预构建,不进行打包操作,依托于浏览器自身对es module的解析,热更新时只更新修正部分,从而到达短时间更新的作用
出产环境:
经过rollup进行打包,rollup支撑原生的tree shaking所以打出来的包体量小 装备项首要分为以下几大类,
- resolve,plugins等共享装备,
- build,打包装备
- build.rollupOptions(rollup底层的装备,将合并vite自身默许的rollup选项),
- server,本地服务装备
- preview,预览装备
- optimizeDeps,
- ssr:服务端烘托装备
vite根本装备
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import jsx from '@vitejs/plugin-vue-jsx'
// 加别号的三种办法
// const path = require("path");//2
import { resolve } from "path" //3 首要用于alias文件途径别号
// // 加别号的函数3
// function pathResolve(dir) {
// return resolve(__dirname, ".", dir)
// }
// https://vitejs.dev/config/
export default defineConfig({
plugins: [vue(),jsx()],
resolve:{
alias:[{//1别号装备
find: '@',
replacement: '/src',
},{
find: '_v',
replacement: '/src/views',
},{
find: '_c',
replacement: '/src/components',
}],
// alias:{ "/c": path.resolve(__dirname, "./src/components"),},//2需求用绝对途径
// alias:{ "/c": pathResolve("src/components"),},//3文件格局已被处理,根目录前不必加/
extensions:['.mjs', '.js', '.ts', '.jsx', '.tsx', '.json','vue']
},
build: {
rollupOptions: {
input: {
main: resolve(__dirname, 'index.html'),
// nested: resolve(__dirname, 'nested/index.html')
}
}
},
server:{
hmr: true, // 敞开热更新
proxy:{
// 选项写法
'/api': {
target: 'http://jsonplaceholder.typicode.com',
changeOrigin: true,
rewrite: (path) => path.replace(/^\/api/, '')
},
}
}
})
对比项 | rollup | webpack | vite |
---|---|---|---|
发动速度 | / | 慢:运行机制:会先进行打包操作,完结之后服务再去恳求资源,时间天然就长了 ;底层原理:js写的 | 快:运行机制:不进行打包操作就不必剖析模块依靠,编译等操作,直接发动开发服务器,然后按需编译(得益于现代浏览器自身支撑es-module);底层原理:根据esbuild进行预构建,速度只有webpack的2%-3%;esbuild用go写的,速度比js写的快10-100倍,go(纳秒级)言语自身相对js(毫秒级)来说就有很大的优势,(并行,线程之间共享内存等)blog.csdn.net/weixin_4386… |
热更新速度 | / | 慢:需求从头将这个模块的一切依靠从头编译 | 快:某个模块内容改动,从头恳求该模块 |
打包速度 | |||
打包体积巨细 | 借助es6模块的静态剖析,只打包用的到代码,比Webpack和Browserify运用的CommonJS模块机制更高效 | 需手动优化,经过插件(uglify)来进行代码紧缩 tree shaking | 有默许装备项,运用rollup进行打包,rollup原生支撑tree shaking和esm |
装备难度 | 小 | 大 | 小,开箱即用,有默许的优化装备 |
兼容性 | / | / | 开发环境因为esm不支撑IE,移动端百度,uc不支撑 |
生态,社区活跃度 | 活跃度高,社区丰厚,老牌打包东西 | 新兴起的东西,社区相比webpack没那么丰厚 | |
运用上 | / | 文件结构不同,能够用require引进资源,经过process.env获取环境变量等 | 项目中不支撑reuqire,经过import引进资源,import.meta.env获取环境变量,变量名必须以VITE_最初 |
问题集锦
- 既然esbuild构建速度这么快为什么vite不必esbuild打包呢?
答:现在暂不支撑代码分隔和css相关处理,可是出产环境的代码仍需一些分包功能来提高运用功能
vite运用问题集锦(vite2.x+vue2.x)
- 运用jsx报错,在script里加上lang=”jsx”
- 不支撑require改用import下的办法引进资源,官方解说,ssr不支撑require 静态资源导入可运用一下两种办法进行导入代替require,或许直接运用途径导入