[7] output(输出)

277 阅读5分钟

一、output对象常用的几个属性

(1)publicPath

默认情况下,webpack-dev-server 会把打包后的文件放到项目的根目录下(path) ,文件名是在output配置中的filename. 但是当有publicPath 配置的时候,就不一样了。

Webpack 会把所有的文件打包到publicPath指定的目录下,就是相当于在项目根目录下创建了一个publicPath目录, 然后把打包成的文件放到了它里面,只不过我们看不到而已, 文件名还是output配置中的filename。

当打包的时候,webpack会在静态文件路径前面添加publicPath的值,当我们把资源放到CDN上的时候,把publicPath的值设为CDN的值就可以了。

Vue CLI 默认值为/,假设你的应用是被部署在一个域名的根路径上,被部署在一个域名的根路径上。

(2)path

经打包代码输出的目录

const path = require('path');

module.exports = {
  //...
  output: {
    path: path.resolve(__dirname, 'dist/assets'), 
  },
};
注意,[fullhash] 在参数中被替换为编译过程(compilation)的 hash。详细信息请查看指南 - 缓存。

output 目录对应一个绝对路径。__dirname项目的路径。

(3)filename

决定了每个输出 bundle 的名称。 filename 是一个很常见的配置,就是对应于 entry 里面的输入文件经过webpack 打包后输出文件的文件名

比如说经过下面的配置,生成出来的文件名为 index.min.js。

 // vue-cli 写法。
chainWebpack(config) {
        const hash = process.env.NODE_ENV === 'development' ? 'hash' : 'contenthash';
        config
            .output
            .filename(`[name].[${hash}:8].js`)
            .end();
  },
 // 源webapck写法
 {
    entry: {
        index: "../src/index.js"  // 【name】为index
    },
    output: {
        filename: "[name].min.js", // index.min.js
    }
}

(4)chunkFilename

决定了每个懒加载的输出 bundle 的名称
背景: 懒加载 (按需加载),初始化不需要加载此代码块,等到具体的执行需要时候,再加载,从而优化性能。

chunkFilename 指未被列在 entry 中,却又需要被打包出来的 chunk 文件的名称。一般来说,这个 chunk 文件指的就是要懒加载的代码。

output:{
    filename,
    chunkFilename: filename
    path:path.resolve(__dirname,'dist')
}

vue-router中路由懒加载写法:

基本语法:import(/* webpackChunkName: "chunk名称(用于代码分割)" */ "组件路径")
在动态import()代码处添加注释webpackChunkName告诉webpack打包后的chunk的名称(注释中的内容很重要,不能省掉),这里打包以后的name就是about。
// 一个路由懒加载的语法
  {
    path: '/about',
    name: 'About',
    // route level code-splitting
    // this generates a separate chunk (about.[hash].js) for this route
    // which is lazy-loaded when the route is visited.
    component: () => import(/* webpackChunkName: "about" */ '../views/About.vue') // 指定chunkName以及可以将多个路由懒加载的组件打包为一个chunk。
  }

默认情况下:

chunkFilename 默认使用 [id].js 或从 output.filename 中推断出的值,ps就是用fileName,不过【name】用id来替换。(其中, [id] 或 [id].去 预替换 [name] )。

懒加载import()写webpackChunkName 时,替换过去【name】。

理解:

output.filename 的输出文件名是 [name].min.js,[name] 根据 entry 的配置推断为 index,所以输出为 index.min.js

由于 output.chunkFilename 没有显示指定,就会把 [name] 替换为 chunk 文件的 id 号,这里文件的 id 号是 1,所以文件名就是 1.min.js。

webapck显式配置chunkFilename,就会按配置的名字生成文件。

output:{
        filename:'[name].bundle.js',
        chunkFilename:'[name].bundle.js',// 决定非入口chunk的名称,动态导入分离代码
        path:path.resolve(__dirname,'dist')
}

二、filename与chunkFilename

filename 指列在 entry 中,打包后输出的文件的名称。

chunkFilename 指未列在 entry 中,却又需要被打包出来的文件的名称,例如懒加载。

三、如何解决浏览器缓存问题?

通过wepack打包时的hash,hash值变了,用户就访问新的了。
filename的hash值可以有三种hash生成方式,分别为hash、chunkHash、contentHash,那它们的区别?

(1) hash

说明:

  • hash是跟整个项目的构建相关,
  • 只要项目里有文件更改,整个项目构建的hash值都会更改,
  • 并且全部文件都共用相同的hash值

举例:

output: {
    filename: '[name].[hash:8].js',
    path: __dirname + '/build'
}

效果分析:

image.png
环境:用于webpack的开发环境
优点:每次的开发中,文件都不会让浏览器器缓存,保证了文件的更新率,提高了开发效率。
问题:多个js文件任何一个改动都会影响另外两个文件的最终文件名。上线后,另外两个文件的浏览器缓存也全部失效。

(2) chunkHash

说明:
chunk 代表模块,根据模块内容计算出来的hash值。 某个文件的改动只会影响它本身的hash指纹,不会影响其他文件。配置webpack的output如下。

从字面上就能猜出它是跟webpack打包的chunk相关的。具体来说webpack是根据入口entry配置文件来分析其依赖项并由此来构建该entry的chunk,并生成对应的hash值。不同的chunk会有不同的hash值。

在生产环境中,我们会把第三方或者公用类库进行单独打包(chunk-vendors),所以不改动公共库的代码,该chunk的hash就不会变,可以合理的使用浏览器缓存了。
举例:

output: {
    filename: '[name].[chunkhash:8].js',
    path: __dirname + '/built'
}

效果分析:

image.png
环境:用于webpack的生产环境

优势:每个文件的hash指纹都不相同,上线后无改动的文件不会失去缓存。

问题:生产环境中我们会用webpack的插件,将css代码打单独提取出来打包(前提) 。这时候chunkhash的方式就不够灵活,因为只要同一个chunk里面的js修改后,css的chunk的hash也会跟随着改动。失去了缓存的意义。因此我们需要contenthash

(3) contentHash

说明:
contenthash主要是处理关联性。
webpack默认将js/style文件统统编译到一个js文件中,可以借助mini-css-extract-plugin将style文件单独编译输出。从这点可以看出,webpack将style文件视为js的一部分。

将css单独编译输出并且打上hash指纹,按照前文所述的使用chunkhash配置输出文件名时,编译的结果是js和css文件的hash指纹完全相同。不论是单独修改了js代码还是style代码,编译输出的js/css文件都会打上全新的相同的hash指纹。 失去了css缓存或者js缓存的优势
举例:

output: {
    filename: '[name].[content:8].js',
    path: __dirname + '/built'
}

效果分析:
环境:用于webpack的生产环境

优势:解决了js和css未改动的缓存问题。

问题:无