Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

webpack 打包文件名加 hash #55

Closed
fantasyroot opened this issue Apr 26, 2018 · 5 comments
Closed

webpack 打包文件名加 hash #55

fantasyroot opened this issue Apr 26, 2018 · 5 comments

Comments

@fantasyroot
Copy link
Contributor

Current behavior

目前 webpack 打包出来的文件名都是不带 hash 的,类似 bundle.css, bundle.js

Expected behavior

期待打包出来的文件名默认带 hash (例如 bundle.8da6c.js),并且 helper.asset 能自动引用带 hash 的文件,解决打包文件更新了但浏览器缓存没更新问题

@fantasyroot
Copy link
Contributor Author

我的临时方案是:
在生产环境启动时,先读取 build 后在项目根目录生成的.stat 文件第一行的 hash,
然后把这个 hash 存放在 helper 扩展里。
在 html 模板里,在静态资源后面加入这个 deploy hash作为参数。这样每次构建之后,都会有不同的 hash。

核心代码:

// app/extend/helper.js
if (app.config.env === 'prod') {
        try {
            const liner = new lineByLine(statsFilePath);
            let line;
            while ((line = liner.next())) {
                let hash = line.toString('ascii').substr(-5);
                if (hash) deployhash = `?${hash}`;
                break; // 只读第一行
            }
        } catch (err) { }
    }
// layout.jsx
helper.asset(`manifest.js${helper.DEPLOY_HASH}`)

@leslie846933
Copy link

我的粗糙解决方案如下:

webpack配置webpack-manifest-plugin,然后将manifest.json传到layout/index.jsx中:

// webpack.config.js

new ManifestPlugin({
	fileName: 'manifest.json',
	manifestVariable: "webpackManifest",
	writeToFileEmit: true,
}),
// app/db/index.js

/**
 * Disk Based JSON Database
 * Only for demo usage.
 * egg-sequelize is recommended in real word scenarios
 * see. https://github.com/eggjs/egg-sequelize
 */
const path = require('path');
const db = require('diskdb');

module.exports = db.connect(path.join(__dirname, '../../build'), [
	'manifest'
]);

// client/layout/index.jsx

const source = this.props.ctx.db.manifest.find();

// css 引用
<link rel="stylesheet" href={helper.asset(source[`${asset}.css`])}/>

// js 引用
<script src={helper.asset(source[`${asset}.js`])}/>

@njugray
Copy link
Contributor

njugray commented May 24, 2018

上面两个方法思路差不多, 把构建后的hash落盘, 在应用中读取, 最后对 helper.asset() 行为做一些定制.

  1. hash生成用 webpack-manifest-plugin 好一些, 给出每个文件对应的hash (contentHash或者 chunkHash), 读取 manifest.json 可以放在 config 里进行:
// config/config.prod.js
const path = require('path');
const fs = require('fs');

function getMainfest() {
  try {
    const mainfestFile = path.join(__dirname, '../build/manifest.json');
    if (fs.existsSync(mainfestFile)) {
      const raw = fs.readFileSync(mainfestFile);
      return JSON.parse(raw);
    }
  } catch (e) {
    return {};
  }
}

module.exports = {
  manifest: getMainfest(),
});

这样做只会在应用启动时读取一次

  1. 定制 asset 方法, 可以在helper里或者context里进行, 这里我给出在 context 里扩展 asset的示例代码:
// app/extend/context.js

module.exports = {
  assetWithHash(asset) {
    // 读取配置中的manifest
    const manifest = this.app.config.manifest || {};
    // 映射文件名
    let filename = asset;
    if (manifest[asset]) {
      filename = manifest[asset];
    }
    return this.asset(filename);
  },
}

manifest.json 中的文件映射关系, 可以更具不同需要, 在 assetWithHash中定制

@ahungrynoob
Copy link
Contributor

webpack-manifest-plugin并不能生成hash,生成hash还是需要修改webpack.config.js中的output去生成,webpack-manifest-plugin只是对这些文件做映射。不知道我这么说对不对

@njugray
Copy link
Contributor

njugray commented Apr 26, 2019

close. support after #161

@njugray njugray closed this as completed Apr 26, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants