在日常项目开发中构建东西是必不可少的,所以也是咱们需求掌握学习的一个重要部分,在技能蓬勃发展的今日,许多优秀的构建东西涌现出来,前端主流打包东西首要有 grunt,gulp,rollup,webpack,vite,parcel等

那么接下来咱们就介绍下比较常用的三个打包东西rollup,webpack,vite对比下这几个打包东西的优缺陷和适用场景

rollup—合适打包类库

Rollup 是一个 JavaScript 模块打包器,他所负责的作业只是把咱们写的代码转化为js

特色:原生支撑tree shaking(去除无用代码),支撑一起生成umd、commonjs,es的代码

缺陷:

  1. 模块过于静态化,HMR很难完结
  2. 仅面向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_最初

问题集锦

  1. 既然esbuild构建速度这么快为什么vite不必esbuild打包呢?

答:现在暂不支撑代码分隔和css相关处理,可是出产环境的代码仍需一些分包功能来提高运用功能

vite运用问题集锦(vite2.x+vue2.x)

  1. 运用jsx报错,在script里加上lang=”jsx”
  2. 不支撑require改用import下的办法引进资源,官方解说,ssr不支撑require 静态资源导入可运用一下两种办法进行导入代替require,或许直接运用途径导入

前端打包工具介绍和对比

前端打包工具介绍和对比