从 vue-cli 到 webpack多入口打包(一)

从三个插件开始

1、CommonsChunkPlugin

commonsChunkPlugin 是webpack中的代码提取插件,可以分析代码中的引用关系然后根据所需的配置进行代码的提取到指定的文件中,常用的用法可以归为四类:(1)、提取node_modules中的模块到一个文件中;(2)、提取 webpack 的runtime代码到指定文件中;(3)、提取入口文件所引用的公共模块到指定文件中;(4)、提取异步加载文件中的公共模块到指定文件中。下面就具体说明以上四种用法。

1.1 提取node_modules中的模块

贴一段vue-cli 生成的代码

new webpack.optimize.CommonsChunkPlugin({
  name: ‘vendor‘,
  minChunks(module) {
    // any required modules inside node_modules are extracted to vendor
    // 所有在node_modules中被引用的模块将被提取到vendor中
    return (
      module.resource &&
      /\.js$/.test(module.resource) &&
      module.resource.indexOf(
        path.join(__dirname, ‘../node_modules‘)
      ) === 0
    )
  }
})
通过查询 commonsChunkPlugin 的相关文档可以知道 options 的配置项中name用于 output 中的 filename的 [name] 占位符,也就是通过name可以指定提取出的文件的文件名或包含name的文件夹名称。minChunks 的取值比较多样

minChunks: number|Infinity|function(module, count) => boolean

这里我们用的是函数的形式,函数接受两个参数,且返回值是boolean类型。函数的作用是遍历所有被引用的模块(module.resource表示的是被引用模块的绝对路径),由此我们可以通过module.resource进行判断,满足条件的我们返回true,反之返回false。返回值为true的模块将被提取到vender中。通过这一步我们可以完成node_modules中模块的提取。

1.2 提取webpack的runtime代码

通过给minChunks传入Infinity这个参数,就可以实现提取webpack的运行时代码。按照官方文档的说法是:

// Passing `Infinity` just creates the commons chunk, but moves no modules into it.
// with more entries, this ensures that no other module goes into the vendor chunk
我个人理解:传入Infinity会生成一个没有包含任何模块的文件,生成这个文件的目的是为了保证vendor和其他公共模块的纯洁性,贴一段vue-cli中的webpack.prod.conf.js文件中的配置代码,并稍作解释:

// extract webpack runtime and module manifest[module manifest => 模块清单] to its own file in order to
// prevent vendor hash from being updated whenever app bundle is updated
new webpack.optimize.CommonsChunkPlugin({
  name: ‘manifest‘,
  minChunks: Infinity
})
[]中注释,manifest是一个模块清单,如果在没有manifest的情况下,我们在业务代码中新引入了一个自定义模块(不是在node_modules中的模块),我们会发现打包的vendeor会发生变化,变化就是因为在vendor中需要指明webpack的模块清单及模块的引用关系。这样我们就无法保证vendor的纯洁性,所以这就是我们提取manifest的必要性。下面会有两张对比图片:

有manifest

无manifest

1.3 提取入口文件所引用的公共模块

如果是在多入口的打包项目中,提取出公共文件可以减少冗余的打包代码。如果是在单入口的应用中,这一步骤可以省略,下面直接贴出代码:

/**
 * 该配置用于在多入口打包中,对 entry chunk中的公共代码进行提取
 */
new webpack.optimize.CommonsChunkPlugin({
  name: ‘common‘, // 如果filename不存在,则使用该配置项的value进行对提取的公共代码进行命名
  filename: ‘common/common-[hash].js‘, // filename 配置项可以指定index.html中的文件引用路径,及提取出来的代码放置路径
  chunks: [...utils.bundleModules], // 需要指定entry chunk 及 menifest
  minChunks: 2 // 指定最小引用次数
})
使用情况如注释中所言,不再赘述。

1.4 提取异步入口中的公共模块到单独文件

如果我们在项目中使用了异步加载模块的形式进行代码打包,异步的文件会作为主入口下的子入口。比较典型的例子就是vue中的异步路由形式,每一个异步路由页面可以作为子入口,而这些入口中的公共代码我们可以将其提取出来到一个公共文件中,从而实现代码的精简。下面看一段路由代码:

routes: [
    {
      path: ‘/‘,
      name: ‘Home‘,
      // 此处采用异步路由的形式,第一个参数是路由所对应的组件路径,最后一个参数是指定[name]占位符
      component: resolve => require.ensure([‘@/modules/moduleA/Home‘], resolve, ‘moduleA/js/home‘)
    },
    {
      path: ‘/add‘,
      name: ‘Add‘,
      component: resolve => require.ensure([‘@/components/Add‘], resolve, ‘moduleA/js/add‘)
    }
]

再贴一段webpack配置代码:

// This instance extracts shared chunks from code splitted chunks and bundles them
// in a separate chunk, similar to the vendor chunk
// see: https://webpack.js.org/plugins/commons-chunk-plugin/#extra-async-commons-chunk
new webpack.optimize.CommonsChunkPlugin({
  names: [...utils.bundleModules],
  async: ‘vendor-async‘,
  children: true,
  minChunks: 2
})

以上两段代码会根据commonsChunkPlugin中names所指定的入口chunk名称进行分别提取,例如names中指定的值为[‘moduleA‘, ‘moduleB‘],webpack会分别找到moduleA和moduleB两个主入口,然后分别在两个主入口中查找异步模块,如果他们各自的异步模块中有共通引用的模块,则这些公共模块会被提取到一个名为vendr-async-moduleA和vendr-async-moduleB的两个文件夹中。

通过以上四个步骤我们基本上可以将常用的公共模块提取到指定的文件中,并且通过commonsChunkPlugin,webpack会自动将依赖文件注入到index.html文件中。完成代码的分割操作。

2、HTMLWebpackPlugin

htmlWebpackPlugin这个插件是用来配置主入口html文件的,具体功能可以通过官方文件了解,这里不再赘述。此处需要说明的是在多入口中htmlWebpackPlugin的配置。

下面贴上vue-cli中的配置:

// generate dist index.html with correct asset hash for caching.
// you can customize output by editing /index.html
// see https://github.com/ampedandwired/html-webpack-plugin
new HtmlWebpackPlugin({
    filename: config.build.index,
    template: ‘index.html‘,
    inject: true,
    minify: {
        removeComments: true,
        collapseWhitespace: true,
        removeAttributeQuotes: true
        // more options:
        // https://github.com/kangax/html-minifier#options-quick-reference
    },
    // necessary to consistently work with multiple chunks via CommonsChunkPlugin
    chunksSortMode: ‘dependency‘
})

上面的配置中指定了template和filename,filename是打包后输出的文件名,filename值是一个字符串,所以可以配置输出的路径和文件名,template用于指定模板文件,同样可以通过字符串的形式指定template的路径和文件名。所以我们可以根据不同的入口配置多个htmlWebpackPlugin,并且指定不同的输出路径,这样就可以将多入口的打包的index.html文件进行区分了。

在webpack的配置中plugins是一个数组,此处我们可以通过循环的方式生成多个htmlWebpackPlugin数组,然后将生成的数组与plugins数组进行合并。多入口配置如下:

// 生成htmlWebpackPlugin数组
const htmlOutput = (function () {
    // utils.bundleModules 是打包的模块列表
    return utils.bundleModules.map(item => {
    // 指定 template 路径
    let template = ‘./src/modules/‘ + item + ‘/index.html‘
    return new HtmlWebpackPlugin({
        // 指定每个index.html 的生成路径,现在的规则下是生成到dist目录下与入口chunk name相同的文件夹下
        filename: path.resolve(__dirname, ‘../dist/‘ + item + ‘/index.html‘),
        template,
        // 此处需要指定 chunks 的值,如果不指定该值,则会默认将所有生成js文件都注入到index.html文件中。实际上我们只希望得到跟当前入口相关的js文件
        chunks: [‘manifest‘, ‘common‘, ‘vendor‘, item],
        // 对文件实行压缩混淆等操作
        minify: {
            removeComments: true,
            collapseWhitespace: true,
            removeAttributeQuotes: true
        },
        // necessary to consistently work with multiple chunks via CommonsChunkPlugin
        chunksSortMode: ‘dependency‘
    })
  })
}())
// ...
// 将生成的htmlOutput 数组拼接到 plugins中
plugins: [
    // 其他插件 ...
    ...htmlOutput
]

通过上面的配置我们就可以顺利将index.html 文件分别打包到我们指定的目录当中。

3、ExtractTextPlugin

通过以上两个配置我们完成了js文件和html文件的分离,并且将他们打包到了指定的目录下。最终我们还剩下css文件没有进行处理。css文件我们通过extractTextPlugin这个插件进行处理,相较于vue-cli中的默认配置,我们改动较小。只需要根据入口来指定打包的位置,见代码:

// vue-cli默认配置,
// extract css into its own file
new ExtractTextPlugin({
    // 所有的文件都统一打包到 dist目录下的css文件夹下
    filename: utils.assetsPath(‘css/[name].[contenthash].css‘),
    // Setting the following option to `false` will not extract CSS from codesplit chunks.
    // Their CSS will instead be inserted dynamically with style-loader when the codesplit chunk has been loaded by webpack.
    // It‘s currently set to `true` because we are seeing that sourcemaps are included in the codesplit bundle as well when it‘s `false`,
    // increasing file size: https://github.com/vuejs-templates/webpack/issues/1110
    allChunks: true
})
// 多入口配置
new ExtractTextPlugin({
    // 将每个入口的css文件提取到各自独立的文件夹下
    // 这里的[name]就是占位符,表示的是 entry中的入口名称
    filename: utils.assetsPath(‘[name]/css/[name].[contenthash].css‘),
    // Setting the following option to `false` will not extract CSS from codesplit chunks.
    // Their CSS will instead be inserted dynamically with style-loader when the codesplit chunk has been loaded by webpack.
    // It‘s currently set to `true` because we are seeing that sourcemaps are included in the codesplit bundle as well when it‘s `false`,
    // increasing file size: https://github.com/vuejs-templates/webpack/issues/1110
    allChunks: true
})

小结

通过以上三个插件我们基本可以将我们需要的代码打包的指定的路径下,并且完成index.html中的文件引用正常,下面我们要做的就是将这三个插件串起来,完成多入口项目的打包。

原文地址:https://www.cnblogs.com/kingsm/p/9964772.html

时间: 2024-11-06 03:28:50

从 vue-cli 到 webpack多入口打包(一)的相关文章

@vue/cli 3 安装搭建及 webpack 配置

首先卸载旧版1 npm uninstall vue-cli -g //or 2 yarn global remove vue-cli 再次安装 1 npm install -g @vue/cli 2 //or 3 yarn global add @vue/cl 查看版本 vue --version //or vue -V 创建项目vue create  my-project //项目名// Windows 上通过 minTTY 使用 Git Bash,交互提示符并不工作.  //你必须通过  

webpack 打包报错:One CLI for webpack must be installed. These are recommended choices, delivered as separate packages

webpack 打包报错: One CLI for webpack must be installed. These are recommended choices, delivered as separate packages: 解决办法: 全局.局部安装个遍!具体什么原因还不清楚... 先全局安装webpack和webpack-clinpm install webpack -gnpm install webpack-cli -g再局部安装webpack和webpack-clinpm inst

手把手教你如何安装使用webpack vue cli

1.安装node.js:https://nodejs.org/en/download/(看电脑的系统是多少位下载相应版本) 我下载的是Windows Installer(.msi) x64 2.打开cmd,查询npm -v看是否有版本号 3.输入指令: 1.npm install -g @vue/cli 2.npm install -g @vue/cli 这两种方式都是全局的(-g) 注意:如果觉得下载速度过于慢了(服务器在国外),可以使用淘宝镜像下载 在cmd中输入: npm install

Vue(四)之webpack和vue-cli

01-webpack介绍 官方文档:https://www.webpackjs.com/concepts/ 本质上,webpack 是一个现代 JavaScript 应用程序的静态模块打包器(module bundler).当 webpack 处理应用程序时,它会递归地构建一个依赖关系图(dependency graph),其中包含应用程序需要的每个模块,然后将所有这些模块打包成一个或多个 bundle. # 全局下载webpack的3.12.0版本 npm install [email pro

Vue CLI 3搭建vue+vuex 最全分析

一.介绍 Vue CLI 是一个基于 Vue.js 进行快速开发的完整系统.有三个组件: CLI:@vue/cli 全局安装的 npm 包,提供了终端里的vue命令(如:vue create .vue serve .vue ui 等命令) CLI 服务:@vue/cli-service是一个开发环境依赖.构建于 webpack 和 webpack-dev-server 之上(提供 如:serve.build 和 inspect 命令) CLI 插件:给Vue 项目提供可选功能的 npm 包 (如

使用vue cli开发项目中遇到的坑

一.部署文件 使用vue cli 开发项目,执行npm run build命令生成dist静态文件,将dist文件包放到服务器中即可. 刚接触webpack,不知道怎么部署前端文件,原以为需要将app文件上传,在 inux上安装node,以及npm install 一系列的包,捣鼓了很久,发现只需要执行 npm run build 将源码打包成一个静态文        文件即可,上传静态文件dist,将 controller指向index.html. 二.跨域问题 实行前后端分离,使用vue i

Vue 2.x + Webpack 3.x + Nodejs 多页面项目框架(下篇——多页面VueSSR+热更新Server)

Vue 2.x + Webpack 3.x + Nodejs 多页面项目框架(下篇--多页面VueSSR+热更新Server) @(HTML/JS) 这是Vue多页面框架系列文章的第二篇,上一篇(纯前端Vue多页面)中,我们尝试从webpack-simple原型项目改造为一个多页面的Vue项目.而这里,我们继续往前,尝试把Vue多页面改造为Nodejs直出.由于步骤较多,所以本文片幅较长. 本文源代码:https://github.com/kenkozheng/HTML5_research/tr

Vue 2.x + Webpack 3.x + Nodejs 多页面项目框架(上篇——纯前端多页面)

Vue 2.x + Webpack 3.x + Nodejs 多页面项目框架(上篇--纯前端多页面) @(HTML/JS) 一般来说,使用vue做成单页应用比较好,但特殊情况下,需要使用多页面也有另外的好处.例如手Q的多webview架构,新开页面有利于ios右划返回,也避免了返回时页面的刷新. 所以,这里我们探讨一下如何配置实现多页面的项目框架.这里是开篇,先以最简单的纯前端多页面为例入手,最终目标是完成Node.js多页面直出+前后端同构的架构. 本文源代码:https://github.c

vue.cli脚手架初次使用图文教程

vue.cli脚手架初次使用图文教程 我之前的环境是安装了node.js, 我记得曾经好像安装过vue ,不过现在又要重新开始学习起来了.在youtube上看了一vue的相关教程,还是需要实操的. 好像安装过npm -v 发现已经安装了5.6.0 需要安装然后使用 cnpm 安装 vue-cli 和 webpack 安装代码:npm install -g vue-cli 一.生成项目 首先需要在命令行中进入到项目目录,然后输入: vue init webpack vue-testone p.p1