欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 新闻 > 焦点 > Webpack5+Babel7+Vue2 初始脚手架构建Demo(附Webpack起源解说)

Webpack5+Babel7+Vue2 初始脚手架构建Demo(附Webpack起源解说)

2024/12/27 8:27:04 来源:https://blog.csdn.net/wangsenling/article/details/144200203  浏览:    关键词:Webpack5+Babel7+Vue2 初始脚手架构建Demo(附Webpack起源解说)

背景

Electron-vue 框架升级 Babel7 并支持electron-preload webapck 4 打包过程记录-CSDN博客 升级 Babel7 成功后,针对 Webpack5 的一些新特性,以及打包速度的提升,想将原来的 Webpack4 版本升级到 Webpack5,但是 Electron-Vue 框架下,不知道什么原因导致升级过后,Webpack 5 无法打包渲染进程,报 vue-loader 找不到的问题,所以就从 0 构建一下 Webpack5 打包 Vue2,以此来分析 Electron-Vue 打包异常的问题。

源码连接

webpack5-vue2-starter: webpack5+vue2+babel7 初始框架,方便大家快速构建自己的vue2代码,也能更清晰的理解vue.config.js 中的配置作用都是什么 - Gitee.com

思路

  1. 想找找 B 站的一些视频来构建,发现视频都是过时的,且现在最新版本 Vue 都是 3.0,B 站的视频已基本不可用,也没有给出具体的 package.json 版本号

  2. 后来想 ChatGPT-o1 应该能解决该问题,所以让 ChatGPT-o1,给了初始化的 package.json 配置,果然很靠谱

什么是 Webpack?

很多前端同学总是模糊地知道这就是个打包的工具,再深了就不知道它到底怎么打包的,这里简要说下它是怎么打包的。

  1. 大家第一开始如果学习的是Java,那估计理解这些东西难上加难,如果从C语言开始学起的,那么就知道程序一开始是面向过程的,也即要把所有的代码都写在一个文件里运行,因此才有goto这种比较可怕的代码,早期的那批程序员就是要记住所有上下文逻辑,还能突然代码一转到一个地方去

    1. 为什么呢?因为想复用代码呗,不想多写这一块的代码,因此使用goto的方式将位置重新定位到这里

    2. 后续我们有了use/import等引入的方式,甚至又出现了函数的概念,使得goto这种关键词已经没有什么意义了

    3. 至于为什么说Java语言入门后很难理解呢?因为到了Java语言层级的时候,就追加了太多的概念了,很多学习Java的人以为程序语言上来就应该是强类型约束,殊不知程序语言一开始是没有类型的,弱类型语言才是程序员的前身,之后因为弱类型语言在团队协作时,甚至单人开发时间跨度较长时也容易忘记传入传出参数是个什么鬼,于是乎一群程序员就要求在弱类型代码的基础上,再重新构建类这个概念,从而以此约束开发者的行为和习惯

    4. 说到这里,大家就应该理解为类本身就是一个对象,这里的对象只能理解为一系列数据的集合,因为这个对象就是造出来约束开发者的

    5. 突破这个概念,你们就能很轻松的理解什么叫指针的概念,有了这玩意,什么类,函数,等等都不重要,这个概念就相当于一个领导指着一堆东西说这是金子一样,所以越底层的开发者为何越喜欢指针,因为只要拿到这玩意,你随便改东西,随便hook,没有逻辑还能约束你,这才是编程真正的快乐。

    6. 讲了那么多,无非还是说程序语言的进化方向就是规则、约束,复用,始终是围绕这三大主题进化,就跟人类社会一样,从创建到发展,无非就是制定越来越多的规则让所有人遵守,好处就是更可控,更稳定,更通用,更复用。

  2. js一开始也没有这些规则,就是面向过程的,而且是弱类型的语言,甚至都没有 `引入` 这个概念,因为仅仅就是作为浏览器脚本语言而已,脚本能有多大?但随着前端规模的不断发展,复杂程度越来越高,甚至一个按钮的都会有复杂的执行动画,里面有大量的js/css/images,这样的按钮下次还想用怎么办?有没有一次性引入的东西,引入了还不影响其他按钮?那就从 js 模块化说起吧,什么叫模块化?

    1. 模块化的意思就是我们如果要想让代码具有可维护性,而不是将全部代码都塞在一个文件里一次性读入内存,那么我们就必须搞一种动态/静态引入的机制,静态引入顾名思义,就是将代码分门别类放在不同的文件夹下下面,在最后打包的时候,通过运行打包脚本,将原来不同文件目录的代码都追加在一个文件里面,这种叫静态引入

      1. 这里再讲下为啥要打包?其实上面已经说到了,面相过程的代码要执行时是按顺序执行的,如果不想goto的话,那就得不断地复制黏贴重复代码,这个过程人怎么能受得了?所以从一开始汇编时就有JUMP的概念,这是最原始的函数了

      2. 但是人和机器是不一样的,机器就是按顺序读入,CPU就是不断地要录入二进制,然后经过电位进行位运算,而你编好的程序就相当于铸造勺子的石模,将一串正常的电位经过你的石模加工后,就变成了可输出的一串电位,这个过程是连续的,而你认为的while循环,只不过是反复将这串电位拷贝再塞入进去的过程

      3. 因此,无论你写的源码存放在不同的目录下,最终都要聚合在一个文件里,形成从上到下的串行过程,执行1,执行2,执行3,再执行1,执行2,执行3,反复这样收尾相接,这就是打包的起源,java就是最好的例子,后来有了动态链接库的概念,就不用一次性整合那么大一个文件了,可以在运行时导入,但是某些代码还是会要聚合在一个文件里,因此打包还是必不可少

      4. PHP和Python为何不用打包呢?因为这货本身就是走的动态引入的方式,是编导入遍编译成二进制,所以不用整合在一个文件里面,理论上你完全可以将他们都整合一个大大二进制文件,然后执行的。

    2. 动态引入的意思,就是打包并不将所有文件都打包到一个文件中,而是连同目录和文件一起拷贝到需要运行的服务器上,服务器从入口文件,一般是 index.js 开始运行,在运行过程中,需要哪些文件,就动态加载到内存里,然后再执行后续逻辑。

    3. 静态模式是早期编程项目规模不大的情况下,例如就十几个 js 文件组成,但是后续前端项目越来越庞大,动辄上百个 js 文件,这些文件分门别类后存放的位置各不相同,同时很多人希望在一个文件内既可以写 css,也可以写 html,更可以追加一下自己的注解

      1. 注解的意思:就相当于老板在文件里写了一句话:给 XX 送个礼,之后这个标记被秘书看到后,秘书就会补充整个送礼的细节和过程,所以执行代码在秘书手里

      2. 注解的出现就是语法糖的意思,很多重复的逻辑过程都可以实现自动化,并非这些过程没有了,而是在打包构建的过程中,由 webpack 这种秘书帮忙补充进去了

      3. 但 Webpack 只是个大管家,它并不负责具体去送礼这件事,而是会找到专门送礼的 loader,由这个 loader 来具体补充送礼的过程

  3. 模块化的进化历程又分为前后端,刚才说了动态引入的过程会将所有目录和文件都放在服务器上,由入口文件启动后,在运行时动态引入,也即代码和服务器都是在一起的,只需要利用文件读写 fs 即可取得具体的代码

    1. 但是浏览器和服务器并不是在一起,虽然这些代码放在服务器上,但是浏览器需要远程获取,获取成功后再动态引入,也即代码的存放位置和实际运行的位置是分开的,但是还想按照模块化的方式进行引入,那就需要异步动态引入,也即向服务器先请求该模块的文件,等请求到了之后,再在本地进行引入。

  4. 那么代码存放和运行在一起的服务,使用的是 CommonJS 协议,而浏览器侧则是代码存放位置和运行位置分离,于是就需要异步引入方式,叫做 AMD,AMD 的问题在于,我写 120 行代码,其中用到 ABC 模块,其中 BC 模块只在某些 if 条件下才会使用,很可能实际运行过程中根本就不会被执行,但是 AMD 不管那么多,一律先全部引入,之后再用,而 CMD 刚好弥补了这个问题,只在 if 条件触发时,开始引入引入 BC 模块,当然后者更完美

  5. 后来 ES6 官方觉得你们这样搞有点乱,不如我来统一搞一些,于是 ES6 又发明了一个官方的引入方式

  6. 这一下子有 4 种引入方式,对我们开发者来说很头大呀!怎么办?谁来救救我们?

  7. 这时候 Webpack 闪亮登场,我来解决你们纠结的事情,我可以根据你们设置的 target:"node|web|electron-main" 来统一解决你们引入协议的问题,而你们只需要按照我给的 import {xxxx} from "xxxxx" 就可以大胆搞事情了

  8. 这就是 Webpack 诞生的原因,用 Webpack 给你的推荐的引入和构建配置方式,来打包你要打包的文件,你可以将所有代码打包到一个 js 里面,也可以按照你的想法动态打包在多个文件里,总之打包和引入的过程,以及模块化的问题你不再需要考虑了。

Webpack5+Vue2 的 package.json 包

{"name": "webpack5vue","version": "1.0.0","description": "","main": "index.js","scripts": {"serve": "webpack serve --mode development","build": "webpack --mode production"},"author": "","license": "ISC","dependencies": {"vue": "^2.6.14","vue-router": "^3.5.2","vuex": "^3.6.2"},"devDependencies": {"@babel/preset-env": "^7.16.0","babel-loader": "^8.2.5","clean-webpack-plugin": "^4.0.0","css-loader": "^6.7.1","css-minimizer-webpack-plugin": "^3.0.0","html-webpack-plugin": "^5.5.0","mini-css-extract-plugin": "^2.4.5","sass": "^1.50.0","sass-loader": "^12.6.0","style-loader": "^3.3.1","terser-webpack-plugin": "^5.1.4","vue-loader": "^15.9.8","vue-style-loader": "^4.1.3","vue-template-compiler": "^2.6.14","webpack": "^5.64.0","webpack-cli": "^4.10.0","webpack-dev-server": "^4.11.0","webpack-merge": "^5.8.0"}
}

webpack.config.js 配置

const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const path = require('path');
const { VueLoaderPlugin } = require('vue-loader');
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');
const TerserPlugin = require('terser-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');  // 引入 html-webpack-plugin 插件module.exports = {entry: './src/main.js',  // Vue 入口文件output: {path: path.resolve(__dirname, 'dist'),filename: 'bundle.js', // 输出的文件名publicPath: '/',  // 配置公共路径},resolve: {alias: {vue$: 'vue/dist/vue.esm.js',  // 配置 Vue 2.x 的构建版本},extensions: ['.js', '.vue', '.json'],},module: {rules: [{test: /\.vue$/,loader: 'vue-loader', // 处理 .vue 文件},{test: /\.js$/,exclude: /node_modules/,use: {loader: 'babel-loader', // 处理 ES6+ 语法options: {presets: ['@babel/preset-env'],},},},{test: /\.css$/,use: ['style-loader',  // 将 CSS 注入到 JS 中'css-loader',    // 处理 CSS 文件],},{test: /\.scss$/,use: ['style-loader','css-loader','sass-loader', // 处理 SCSS 文件],},{test: /\.(png|jpe?g|gif|svg)$/,use: [{loader: 'file-loader', // 处理图片文件options: {name: '[name].[hash:7].[ext]',outputPath: 'assets/images/',},},],},],},plugins: [new VueLoaderPlugin(), // Vue 2 的加载器插件new CleanWebpackPlugin(),  // 每次构建时清理 dist 文件夹new HtmlWebpackPlugin({template: './public/index.html',  // 使用 public 文件夹中的 index.html 模板filename: 'index.html',  // 输出的 HTML 文件名inject: true,  // 自动注入 js 和 css}),new MiniCssExtractPlugin({filename: '[name].[contenthash].css',  // 提取出的 CSS 文件}),],optimization: {minimize: true,minimizer: [new TerserPlugin({terserOptions: {ecma: 5,  // 保持兼容 ES5},}),new CssMinimizerPlugin(), // CSS 最小化插件],},devtool: 'source-map',  // 生成 source mapdevServer: {static: {directory: path.resolve(__dirname, 'dist'),  // 设定静态文件目录},compress: true,port: 9000, // 开发服务器端口open: true, // 启动后自动打开浏览器hot: true, // 启用热模块替换historyApiFallback: true,  // 单页应用处理 404 错误},
};

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com