webpack本地配置-一文搞懂Webpack多入口配置

2023-08-29 0 5,687 百度已收录

点击蓝字“前端技术优化”关注我们!

最近做项目的时候,遇到一个场景:一个项目有多个入口,不同的入口、路由、组件、资源等有重叠的部分,也有不同的部分。 由于不同条目下的一些路由页面是重复的,所以我考虑使用Webpack多条目配置来解决这个需求。

再次,我在网上找到的很多文章都不能满足我的需求。 很多文章只简单介绍了生产环境中的配置,而没有介绍开发环境中的配置,有的没有将多个条目与 vue-router 和 vuex 、 ElementUI 等结合起来,所以我会继续探索坑下面,再把思路和配置过程记录下来,给自己留个笔记,分享给大家,希望能帮助到有同样需求的朋友~

1. 目标分析

一个项目中保存了多个HTML模板,不同的模板有不同的入口,有自己的router、store等;

不仅可以封装不同的HTML,而且在开发过程中也可以顺利调试;

不同条目的文件可以引用相同的组件、镜像等资源,也可以引用不同的资源;

代码仓库:multi-entry-vue

示意图如下:

2. 准备工作

首先,我们使用 vue init webpack multi-entry-vue 使用 vue-cli 创建一个 webpack 模板项。 文件结构如下:

  1. .

  2. ├── build

  3. ├── config

  4. ├── src

  5.    ├── assets

  6.       └── logo.png

  7.    ├── components

  8.       └── HelloWorld.vue

  9.    ├── router

  10.       └── index.js

  11.    ├── App.vue

  12.    └── main.js

  13. ├── static

  14. ├── README.md

  15. ├── index.html

  16. ├── package-lock.json

  17. └── package.json

顺便说一下,下面是不同系统下生成目录树的方法:

mac系统命令行生成目录树tree -I node_modules --dirsfirst,该命令的意思是不显示node_modules路径下的文件,先对文件夹进行排序生成目录树。 如果报没有找到tree命令的错误,只需安装tree命令行brew install tr​​ee即可。

windows系统可以使用目标目录中的tree/f1.txt将当前目录树生成为新文件1.txt。

首先简单介绍一下Webpack的相关配置项。 这些配置项一般根据使用的Webpack模板存放在webpack.config.js或webpack.base.conf.js中:

  1. const path = require('path')

  2. module.exports = {

  3. context: path.resolve(__dirname, '../'),

  4. entry: {

  5. app: './src/main.js'

  6. },

  7. output: {

  8. path: path.resolve(__dirname, '../dist'),

  9. filename: 'output-file.js',

  10. publicPath: '/'

  11. },

  12. module: {}, // 文件的解析 loader 配置

  13. plugins: [], // 插件,根据需要配置各种插件

  14. devServer: {} // 配置 dev 服务功能

  15. }

这个配置意味着Webpack执行后,会在命令的执行目录下创建一个新的dist目录(如果需要的话),并将src目录下的main.js及其依赖包打包生成output-file.js目录中的 dist。

下面简单解释一下相关配置项:

Entry:入口文件配置项,可以是字符串、对象或数组。 以里面的object方法为例,app是入口名称,如果output.filename中有[name],则会替换为app。

context:webpack编译时的基本目录。 用于解析入口选项的基本目录(绝对路径)。 入口条目的起始点将会相对于这个目录进行搜索,相当于一个公共目录。 以下所有目录都在这个公共目录下。

output:导出文件的配置项。

output/path:打包文件输出的目录,比如之前的dist,那么输出文件会放在与当前目录同级目录的dist文件夹下,如果有则新建一个没有这样的文件夹。 可以配置为path.resolve(__dirname,'./dist/${Date.now()}/')(md语法不方便改成模板字符串,请自行更改),以方便持续集成。

output.filename:输出文件的名称,[name]表示根据入口文件的名称打包成同名的,有几个入口,可以打包几个文件。 例如,条目的键是app,包是app.js,条目是my-entry,包是my-entry.js。

output.publicPath:静态资源的公共路径,可以记住这个公式:静态资源最终访问路径=output.publicPath+资源加载器或插件配置路径。 例如publicPath配置为/dist/,图片的url-loader配置项为name:'img/[name].[ext]',则输出最终打包文件中图片的引用路径.publicPath+'img/ [名称].[ext]'='/dist/img/[名称].[ext]'。

由于本文涉及入口和出口的配置,因此内容主要围绕入口、输出以及一个重要的webpack插件html-webpack-plugin进行。 该插件与打包的HTML文件密切相关,主要有以下功能:

根据模板生成HTML文件;

在生成的HTML文件中引入链接、脚本等外部资源;

更改每个导入的外部文件的Hash,以防止HTML引用缓存中过时的资源;

让我们从头开始逐步配置一个多条目项目。

3.开始配置 3.1 文件结构改变

复制src目录下的main.js和App.vue两个文件。 随着不同的条目,文件结构变为:

  1. .

  2. ├── build

  3.    ├── build.js

  4.    ├── check-versions.js

  5.    ├── logo.png

  6.    ├── utils.js

  7.    ├── vue-loader.conf.js

  8.    ├── webpack.base.conf.js

  9.    ├── webpack.dev.conf.js # 主要配置目标

  10.    └── webpack.prod.conf.js # 主要配置目标

  11. ├── config

  12.    ├── dev.env.js

  13.    ├── index.js

  14.    └── prod.env.js

  15. ├── src

  16.    ├── assets

  17.       └── logo.png

  18.    ├── components

  19.       └── HelloWorld.vue

  20.    ├── router

  21.       └── index.js

  22.    ├── App.vue

  23.    ├── App2.vue # 新增的入口

  24.    ├── main.js

  25.    └── main2.js # 新增的入口

  26. ├── static

  27. ├── README.md

  28. ├── index.html

  29. └── package.json

3.2 简单配置

为了从不同的入口打包不同的HTML,我们可以改变入口和输出两个配置。

  1. // build/webpack.prod.conf.js


  2. module.exports = {

  3. entry: {

  4. entry1: './src/main.js',

  5. entry2: './src/main2.js'

  6. },

  7. output: {

  8. filename: '[name].js',

  9. publicPath: '/'

  10. },

  11. plugins: [

  12. new HtmlWebpackPlugin({

  13. template: "index.html", // 要打包输出哪个文件,可以使用相对路径

  14. filename: "index.html" // 打包输出后该html文件的名称

  15. })

  16. ]

  17. }

根据上一节我们知道,如果webpack配置中的output.filename有[name],则表示会根据入口文件的名称打包成对应名称的JS文件,所以现在我们可以打包entry.js和entry2。 js.

打包结果如下:

当前代码:Github - multi-entry-vue1

如上图所示,此时我们通过npm run build打包了一个引用这两个文件的index.htmlwebpack本地配置,那么如何打包不同的HTML文件,分别应用不同的入口JS文件呢? 这时候我们就需要用到插件HtmlWebpackPlugin。

HtmlWebpackPlugin 插件是一个新插件,它打包一个 HTML 页面,因此我们可以通过在插件配置中添加两个新插件来打包两个页面。

3.3 打包不同的HTML页面

我们将配置文件更改为以下内容:

  1. // build/webpack.prod.conf.js


  2. module.exports = {

  3. entry: {

  4. entry: './src/main.js', // 打包输出的chunk名为entry

  5. entry2: './src/main2.js' // 打包输出的chunk名为entry2

  6. },

  7. output: {

  8. filename: '[name].js',

  9. publicPath: '/'

  10. },

  11. plugins: [

  12. new HtmlWebpackPlugin({

  13. filename: 'entry.html', // 要打包输出的文件名

  14. template: 'index.html', // 打包输出后该html文件的名称

  15. chunks: ['manifest', 'vendor', 'entry'] // 输出的html文件引入的入口chunk

  16. // 还有一些其他配置比如minify、chunksSortMode和本文无关就省略,详见github

  17. }),

  18. new HtmlWebpackPlugin({

  19. filename: 'entry2.html',

  20. template: 'index.html',

  21. chunks: ['manifest', 'vendor', 'entry2']

  22. })

  23. ]

  24. }

上面的配置要注意chunks。 如果没有配置,生成的HTML会导入所有入口JS文件。 在前面的例子中,生成的两个HTML文件也会导入entry.js和entry2.js,因此使用chunks配置来指定生成的HTML文件应该导入哪些JS文件。 配置好 chunk 后,不同的 HTML 只能导入 chunk 对应的 JS 文件。

你不仅可以看到我们打包生成的块文件entry.js和entry2.js,还可以看到manifest和vendor。 下面简单解释一下这两个块:

Vendor是指提取node_modules中涉及的公共模块;

清单是供应商模块的缓存;

打包结果如下:

文件结构:

现在打包的样式正是我们所需要的。 这时我们启动dist目录下的live-server(如果还没有安装,可以先安装npm ig live-server),就可以看到疗效了:

当前代码:Github - multi-entry-vue2

至此webpack本地配置,一个简单的多入口项目的配​​置就已经实现了。

4. 配置改进 4.1 文件结构变更

我们在上一篇文章中配置了多个条目。 要创建新条目,请复制多个文件,然后自动更改相应的配置。

但如果不同的vue-router和vuex放在不同的html文件下的src目录下,并且多个条目的内容平铺在一起,项目目录会显得杂乱、不清晰,所以将多条目相关文件放在下面在一个单独的文件夹中,如果将来有更多条目,它们将在该文件夹中处理。

让我们更新一下文件结构:

首先我们在根目录下创建一个entries文件夹,将不同entry的router、store、main.js放在这里,并将每个entry放在单独的文件夹中;

在src目录下构建common文件夹,用于存放多个条目共享的组件等;

当前目录结构:

  1. .

  2. ├── build # 没有改动

  3. ├── config # 没有改动

  4. ├── entries # 存放不同入口的文件

  5.    ├── entry1

  6.       ├── router # entry1 的 router

  7.          └── index.js

  8.       ├── store # entry1 的 store

  9.          └── index.js

  10.       ├── App.vue # entry1 的根组件

  11.       ├── index.html # entry1 的页面模版

  12.       └── main.js # entry1 的入口

  13.    └── entry2

  14.    ├── router

  15.       └── index.js

  16.    ├── store

  17.       └── index.js

  18.    ├── App.vue

  19.    ├── index.html

  20.    └── main.js

  21. ├── src

  22.    ├── assets

  23.       └── logo.png

  24.    ├── common # 多入口通用组件

  25.       └── CommonTemplate.vue

  26.    └── components

  27.    ├── HelloWorld.vue

  28.    ├── test1.vue

  29.    └── test2.vue

  30. ├── static

  31. ├── README.md

  32. ├── index.html

  33. ├── package-lock.json

  34. └── package.json

4.2 webpack配置

然后我们在build/utils文件中添加两个函数,分别生成webpack入口配置和HtmlWebpackPlugin插件配置。 因为我们需要使用node.js读取文件夹结构,所以需要引入fs、glob等模块:

  1. // build/utils

  2. const fs = require('fs')

  3. const glob = require('glob')

  4. const merge = require('webpack-merge')

  5. const HtmlWebpackPlugin = require('html-webpack-plugin')

  6. const ENTRY_PATH = path.resolve(__dirname, '../entries')


  7. // 多入口配置,这个函数从 entries 文件夹中读取入口文件,装配成webpack.entry配置

  8. exports.entries = function() {

  9. const entryFiles = glob.sync(ENTRY_PATH + '/*/*.js')

  10. const map = {}

  11. entryFiles.forEach(filePath => {

  12. const filename = filePath.replace(/.*/(w+)/w+(.html|.js)$/, (rs, $1) => $1)

  13. map[filename] = filePath

  14. })

  15. return map

  16. }


  17. // 多页面输出模版配置 HtmlWebpackPlugin,根据环境装配html模版配置

  18. exports.htmlPlugin = function() {

  19. let entryHtml = glob.sync(ENTRY_PATH + '/*/*.html')

  20. let arr = []

  21. entryHtml.forEach(filePath => {

  22. let filename = filePath.replace(/.*/(w+)/w+(.html|.js)$/, (rs, $1) => $1)

  23. let conf = {

  24. template: filePath,

  25. filename: filename + '.html',

  26. chunks: [filename],

  27. inject: true

  28. }


  29. // production 生产模式下配置

  30. if (process.env.NODE_ENV === 'production') {

  31. conf = merge(conf, {

  32. chunks: ['manifest', 'vendor'],

  33. minify: {

  34. removeComments: true,

  35. collapseWhitespace: true,

  36. removeAttributeQuotes: true

  37. },

  38. chunksSortMode: 'dependency'

  39. })

  40. }

  41. arr.push(new HtmlWebpackPlugin(conf))

  42. })

  43. return arr

  44. }

对这两个函数的一点解释:

Exports.entries函数从entries文件夹中查找二级目录下的JS文件作为入口文件,并以二级目录的文件夹名作为key生成这样一个对象:{"entry1":"/multi-entry -vue /entries/entry1/main.js"},多个条目的情况下会有更多的通配符对;

Exports.htmlPlugin函数的原理和前面的函数类似,只不过是组装了HtmlWebpackPlugin插件的配置,并生成了这样一个链表。 可以看到和我们自动设置的配置基本一样,只不过现在是按照文件夹结构生成的:

  1. // production 下

  2. [

  3. {

  4. template: "/multi-entry-vue/entries/entry1/index.html",

  5. chunks: ['manifest', 'vendor', 'entry1'],

  6. filename: "entry1.html",

  7. chunksSortMode: 'dependency'

  8. },

  9. { ... } // 下一个入口的配置

  10. ]

有了这两个函数来根据entries文件夹的结构手动生成webpack配置,我们来更改几个与webpack相关的配置文件:

  1. // build/webpack.base.conf.js


  2. module.exports = {

  3. entry: utils.entries(), // 使用函数生成 entry 配置

  4. output: {

  5. path: config.build.assetsRoot,

  6. filename: '[name].js',

  7. publicPath: process.env.NODE_ENV === 'production'

  8. ? config.build.assetsPublicPath

  9. : config.dev.assetsPublicPath

  10. }

  11. }

  1. // build/webpack.dev.conf.js


  2. // const HtmlWebpackPlugin = require('html-webpack-plugin') // 不需要了


  3. const devWebpackConfig = merge(baseWebpackConfig, {

  4. devServer: {

  5. historyApiFallback: {

  6. rewrites: [ // 别忘了把 devserver 的默认路由改一下

  7. { from: /.*/, to: path.posix.join(config.dev.assetsPublicPath, 'entry1.html') },

  8. ],

  9. }

  10. },

  11. plugins: [

  12. // https://github.com/ampedandwired/html-webpack-plugin

  13. // new HtmlWebpackPlugin({

  14. // filename: 'index.html',

  15. // template: 'index.html',

  16. // inject: true

  17. // }), // 注释掉原来的 HtmlWebpackPlugin 配置,使用生成的配置

  18. ].concat(utils.htmlPlugin())

  19. })

  1. // build/webpack.prod.conf.js


  2. // const HtmlWebpackPlugin = require('html-webpack-plugin')


  3. const webpackConfig = merge(baseWebpackConfig, {

  4. plugins: [

  5. // new HtmlWebpackPlugin({

  6. // ... 注释掉,不需要了

  7. // }),

  8. ].concat(utils.htmlPlugin())

  9. })

现在让我们再次运行 npm run build 来看看生成的目录是什么样的:

此时,我们在dist目录下启动live-server,看看有什么效果:

当前代码:Github - multi-entry-vue3

网上的帖子大多是深浅不一,甚至有些前后矛盾。 以下文章是学习过程的总结。 如果发现有错误的地方请留言强调哦~

参考:

webpack困惑:多入口文件打包策略

webpack配置文件:入口和出口、多入口、多出口配置

一目了然了解 webpack 中间配置和优化


在看点这里

收藏 (0) 打赏

感谢您的支持,我会继续努力的!

打开微信/支付宝扫一扫,即可进行扫码打赏哦,分享从这里开始,精彩与您同在
点赞 (0)

悟空资源网 webpack webpack本地配置-一文搞懂Webpack多入口配置 https://www.wkzy.net/game/181561.html

常见问题

相关文章

官方客服团队

为您解决烦忧 - 24小时在线 专业服务