Vue2:webpack

打包工具:项目工程化工具

 

什么是webpack?(面试题)

webpack 是代码编译工具,有入口、出口、loader 和插件。webpack 是一个用于现代 JavaScript 应用程序的静态模块打包工具。

 

webpack 是一个打包模块化 javascript 的工具,在webpack 里一切文件皆模块,通过 loader 转换文件,通过 plugin 注入钩子,最后输出由多个模块组合成的文件,webpack 专注构建模块化项目; webpack 可以看做是模块打包机:它做的事情是,分析你的项目结构,找到JavaScript 模块以及其它的一些浏览器不能直接运行的拓展语言(Scss,TypeScript等),并将其打包为合适的格式以供浏览器使用

 

 

还有哪些常见的打包工具?

1、grunt 与 gulp

https://www.gruntjs.net/

https://www.gulpjs.com.cn/

 

2、snowpack

特点:速度快

http://www.snowpack.cn/

 

3、parcel

https://www.parceljs.cn/getting_started.html

 

4、esbuild

https://esbuild.github.io/

 

 

5、rollup

https://www.rollupjs.com/

 

6、vite

vite是下一代前端开发与构建工具。 Vite意在提供开箱即用的配置,同时它的插件API和JavaScript API 带来了高度的可扩展性,并有完整的类型支持,上线时间2019年,一套构建指令,它使用Rollup打包代码,并且它是预配置的,可输出用于生产环境的高度优化过的静态资源。

https://vitejs.cn/

7、webpack

https://webpack.docschina.org/

 

 

webpack 与 grunt、gulp 的不同?

1、三者之间的区别 三者都是前端构建工具,grunt 和 gulp 在早期比较流行,现在webpack相对来说比较主流,不过一些轻量化的任务还是会用 gulp 来处理,比如单独打包CSS文件等

1.1grunt 和 gulp 是基于任务和流(Task、Stream)的。类似jQuery,找到一个(或一类)文件,对其做一系列链式操作,更新流上的数据,整条链式操作构成了一个任务,多个任务就构成了整个 web 的构建流程。

1.2webpack 是基于入口的。webpack 会自动地递归解析入口所需要加载的所有资源文件,然后用不同的 Loader 来处理不同的文件,用 Plugin 来扩展webpack功能。

2、构建思路的区别

2.1gulp 和 grunt 需要开发者将整个前端构建过程拆分成多个Task,并合理控制所有Task的调用关系

2.2webpack 需要开发者找到入口,并需要清楚对于不同的资源应该使用什么Loader 做何种解析和加工

3、 从知识背景区别

3.1gulp 更像后端开发者的思路,需要对于整个流程了如指掌

3.2webpack 更倾向于前端开发者的思路

 

 

核心概念

 

 

webpack环境安装

*这里下载5.0版本

npm install webpack webpack-cli -g//不指定版本,默认下载最新版本,全局安装以后直接使用
mkdir webpack-demo //创建项目文件夹,随意名字同js变量名规则
cd webpack-demo //进入项目文件夹
npm init -y //生成项目配置文件

创建一个webpack.config.js的打包配置文件
代码:
module.exports={
     项目入口配置,
     项目出口配置,
     加载器配置,
     插件配置,
     开发模式配置,
     其他
}

 



项目入口配置

在webpack.config.js文件内配置

//1.直接配置入口文件
module.exports = {
  entry: './path/to/my/entry/file.js', //输出时默认为main.js
};



//2.配置基础目录,然后配置入口文件
module.exports = {
  context: __dirname+'/app', 
  entry:"./test.js"  //相对于context的路径 
};



//3.多入口
module.exports = {
    context: __dirname + '/app', 
    entry: {
        a: './test.js',      //输出时默认为a.js
        b: './test2.js',     //输出时默认为b.js
        test3: './test3.js'  //输出时默认为test3.js
    }
}

//4.多入口
module.exports = {
    context: __dirname + '/app', 
    entry: ['./test.js','./test2.js', './test3.js']    //输出时默认为main.js,而且全部打包在一起
}
总结:如果传入一个字符串或字符串数组,chunk 会被命名为 main。如果传入一个对象,则每个属性的键(key)会是 chunk 的名称,该属性的值描述了 chunk 的入口点。


//5.入口配置
module.exports = {
  context: __dirname + '/app',
  entry: {
      //输出时默认为a.js
    a: './test.js',
     //输出时默认为pages文件夹下的b.js  
    b: { import: './test2.js', filename: 'pages/[name].js' },
     //输出时默认为pages文件夹下的c666.js
    c: { import: './test3.js', filename: 'pages/[name]666.js' }
       //输出时默认为pages文件夹下的d+哈希值+666.js
    d: { import: './test4.js', filename: 'pages/[name][hash]666.js' }
        //输出时默认为pages文件夹下的e+3位哈希值+666.js
    e: { import: './test5.js', filename: 'pages/[name][hash:3]666.js' }
  }
};

总结:  
1.[name]代表entry的当前属性名  [hash]代表哈希值
2.配置对象除了import和filename还有很多,比如做加载相关的asyncChunks,自行查官网了解

 

名字解释 bundle,chunk,module 是什么?(面试题)

 

1、module:开发中的每一个文件都可以看作是 module,模块不局限于js,也包含css,图片等

2、chunk:表示代码块,一个 chunk 可以由多个模块组成

3、bundle:最终打包完成的文件,一般就是和 chunk 一一对应的关系,bundle就是对 chunk 进行编译压缩打包等处理后的产出

 

 

项目出口配置

 

module.exports = {
    mode: "none",
    context: __dirname + '/app',
    // entry:'./test.js',
    entry: {
        a: './test.js'
    },
    output: {
        asyncChunks: true, //创建按需加载的异步 chunk。
        
        path:__dirname+"/dist2",//输出的目录,绝对路径,默认dist
        
        // filename: 'bundle.js', //输出的文件名
        filename: '[name]-666-[id]bundle[hash:5].js', //输出的文件名,[hash:5]为5位哈希值,[id]为打包的chunk的id,[name]为入口的属性名,缺省则为mian,这几个一定记住 vue和react的css作用域-就是这个几个设计的
            
        
        // library: 'hqyj',//库名
        library: {
            name: 'MyLibrary', //库名
            type: 'var', //配置将库暴露的方式。('var'、'module'、'assign'、'assign-properties'、'this'、'window'、'self'、'global'、'commonjs'、'commonjs2'、'commonjs-module'、'commonjs-static'、'amd'、'amd-require'、'umd'、'umd2'、'jsonp' 以及 'system')
        },
        // libraryTarget: 'umd',//配置如何暴露 library,优先级比library高但是:[请使用 output.library.type 代理,因为我们可能在未来放弃对 output.libraryTarget 的支持。]
        
        
        
        
        auxiliaryComment: 'Test Comment', //各种模块化导出技术的统一注释(把type设置为umd)      
        //各种模块化导出技术的分别注释(webpack允许你的项目使用各种模块化技术 它都可以识别并打包)
        // auxiliaryComment: {
        //     root: 'Root Comment',
        //     commonjs: 'CommonJS Comment',
        //     commonjs2: 'CommonJS2 Comment',
        //     amd: 'AMD Comment',
        // },    


        clean: true, // 在生成文件之前清空 output 目录
        // clean: {
        //       dry: true, // 小黑窗打印而不是删除应该移除的静态资源
        //     },
        // clean: {
        //     keep: /ignored\/dir\//, // 保留 'ignored/dir' 下的静态资源不删
        //     // keep(asset) {
        //     //     return asset.includes('ignored/dir');//同上
        //     // },
        // },        
    }
};

 

 

加载器配置

1、css-loader&style-loader

下载命令:npm install css-loader style-loader --save-dev

配置:

module.exports={     
     //加载器配置loader,
       module:{
           rules:[
               {test:/\.css$/,use:["style-loader","css-loader"]}//use数组的加载是从后向前解析
           ]
       }
}

 

2、file-loader

下载命令:npm i file-loader --save-dev

配置:

module: {
    rules: [
        //直接以style标签形式动态写入到页面
        {test:/\.css$/,use:["style-loader","css-loader"]},
        //项目中引入了以下结尾的文件就会启动file-loader
        {test:/\.(png|jpg|jpeg|mp4|mp3)$/,use:["file-loader"]},
    ]
},

 

3、ts-loader

下载命令:npm install ts-loader webpack typescript --save-dev

配置:

module: {
        rules: [
            //直接以style标签形式动态写入到页面
            // {test:/\.css$/,use:["style-loader","css-loader"]},
            {
                test: /\.css$/,
                //css生成到css文件中,项目中以<link>形式引入使用
                use: [MiniCssExtractPlugin.loader, 'css-loader']
            },
            {test:/\.(png|jpg|jpeg|mp4|mp3)$/,use:["file-loader"]},
            { test: /\.ts$/, use: 'ts-loader' },
        ]
    },

 

4、babel-loader

下载命令:npm install babel-loader @babel/core @babel/preset-env webpack -D

配置:

module: {
        rules: [
            //直接以style标签形式动态写入到页面
            // {test:/\.css$/,use:["style-loader","css-loader"]},
            {
                test: /\.css$/,
                //css生成到css文件中,项目中以<link>形式引入使用
                use: [MiniCssExtractPlugin.loader, 'css-loader']
            },
            {test:/\.(png|jpg|jpeg|mp4|mp3)$/,use:["file-loader"]},
            { test: /\.ts$/, use: 'ts-loader' },
            //exclude:/node_module/ 意思是下载的模块不转码,其他js文件转码
             {
                  test: /\.js$/,
                  exclude: /(node_modules|bower_components)/,
                  use: {
                    loader: 'babel-loader',
                    options: {
                      presets: ['@babel/preset-env'],
                      plugins: ['@babel/plugin-proposal-object-rest-spread']
                    }
                  }
                }
        ]
    },

 

5、sass-loader

下载命令:npm install sass-loader sass webpack --save-dev

配置:

 module: {
    rules: [
      {
        test: /\.s[ac]ss$/i,
        use: [        
          'style-loader',  //不用单独引入 直接运行js代码 动态写入页面    
          'css-loader',
          // 将 Sass 编译成 CSS
          'sass-loader',
        ],
      },
    ],
  },

 

 

插件配置

1、EslintWebpackPlugin

环境准备:

npm install eslint-webpack-plugin --save-dev

如果未安装 eslint >= 7 ,你还需先通过 npm 安装:

npm install eslint --save-dev

插件配置:

const ESLintPlugin = require('eslint-webpack-plugin');

module.exports = {
  // ...
  plugins: [new ESLintPlugin(options)],
  // ...
};


//options的参数配置:
context:__dirname+"/src" //指定文件根目录
extensions:String|Array[String] //指定需要检查的扩展名.不配置默认为"js"
exclude:"node_modules" //指定需要排除的文件及目录。必须是相对于 options.context 的相对路径。
files:String|Array[String] //指定目录、文件或 globs ,必须是相对于 options.context 的相对路径。 如果是目录则递归查找所有匹配 options.extensions 选项的文件。 

 

 

2、HtmlWebpackPlugin

安装:

npm install --save-dev html-webpack-plugin

配置:

const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
  entry: 'index.js',
  output: {
    path:__dirname+'/dist',
    filename: 'bundle.js',
  },
  plugins: [new HtmlWebpackPlugin()],
};
//该插件将为你生成一个HTML5 文件, 在 body 中使用 `script` 标签引入你所有 webpack 生成的bundle.js。 
//但是每次生成的模板都是新的 

 

 

开发模式配置

安装:npm install --save-dev webpack webpack-dev-server webpack-cli

配置:

module.exports = {
    devServer: {
        //告诉dev-server在服务器启动后打开浏览器。将其设置为true以打开默认浏览器。但是:如果你的电脑有防火墙或者有管理员权限的限制或者电脑很卡 可能不会自定打开浏览器
        open: true, //cli中 webpack serve --open                    
                        
        //本地服务器监听的端口
        port: 8080,
        
        //启用热更新,直接使用webpack的热更新模块.就是改了代码自动打包后自定刷新浏览器页面:bug就是同open,记住 卡了就刷新一下不用纠结
        hot: true,
        
        //指定要使用的主机(localhost|ipv4|ipv6)。如果你想让你的服务器可以被外部访问,像这样指定:
        //让你同桌访问 然后你改项目代码 他就会刷新
        host: '192.168.2.60',
        
        //启用gzip压缩
        compress: true,
            
        //代理配置,这里只是配置,不用写代理服务器的代码(配置好了它帮我们实现)
        proxy: {
            '/api': 'http://localhost:7001',
        },
         // proxy: {
         //      '/api': {
         //        target: 'http://localhost:7001',
         //        secure:true,//如果代理的target是https接口,需要配置它 
         //        pathRewrite: { '^/api': '/chongxie' },//请求时重写pathname
         //      },
         //    },
       }        
    }

启动命令:

webpack server

 

package.json指令相关

 

//package.json文件: 
 "scripts": {
    "dev": "webpack server",
    "build": "webpack"
  },
      //开发阶段 npm run dev 不会打包到磁盘 
      //生产阶段 npm run build 打包生成到磁盘

 

开发依赖和生产依赖

引入网络请求工具

下载  npm i axios --save

然后再main.js中引入:

  import axios from "axios"

面试题:

webpack的cli配置中有--watch的观察模式 为什么还要配置服务?或者说devServer的优势是什么?

答:

devServer的功能是:当文件发生修改,通知各个模块进行更新加载,加载到计算机内存,刷新浏览器

1.项目中加载的东西很多.内存刷新 比磁盘刷新反应快

2.热更新使得开发调试效率更高

3.自动配置代理 比手动设计代理服务器更方便

 

 

webpack 的构建流程是什么?从读取配置到输出文件这个过程

答:

webpack 的运行流程是一个串行的过程,从启动到结束会依次执行以下流程:

1、初始化参数:从配置文件和 Shell 语句中读取与合并参数,得出最终的参数

2、开始编译:用上一步得到的参数初始化 Compiler 对象,加载所有配置的插件,执行对象的 run 方法开始执行编译

3、确定入口:根据配置中的 entry 找出所有的入口文件

4、编译模块:从入口文件出发,调用所有配置的 Loader 对模块进行翻译,再找出该模块依赖的模块,再递归本步骤直到所有入口依赖的文件都经过了本步骤的处理

5、完成模块编译:在经过第 4 步使用 Loader 翻译完所有模块后,得到了每个模块被翻译后的最终内容以及它们之间的依赖关系

6、输出资源:根据入口和模块之间的依赖关系,组装成一个个包含多个模块的Chunk, 再把每个 Chunk 转换成一个单独的文件加入到输出列表,这步是可以修改输出内容的最后机会

7、输出完成:在确定好输出内容后,根据配置确定输出的路径和文件名,把文件内容写入到文件系统,在以上过程中,webpack 会在特定的时间点广播出特定的事件,插件在监听到感兴趣的事件后会执行特定的逻辑,并且插件可以调用webpack 提供的API改变 webpack 的运行结果

 

 

如何利用 webpack 来优化前端性能

答:

1、压缩代码。uglifyJsPlugin 压缩 js 代码, mini-css-extract-plugin 压缩css代码

2、利用 CDN 加速,将引用的静态资源修改为 CDN 上对应的路径,可以利用webpack对于 output 参数和 loader 的 publicpath 参数来修改资源路径

3、删除死代码(tree shaking),css 需要使用 Purify-CSS

4、 提取 公共 代码集成为模块 。

 

 

 

posted on 2022-08-26 20:39  香香鲲  阅读(612)  评论(0编辑  收藏  举报