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

build 生产环境不支持 hash文件名吗? #69

Closed
Superman-wc opened this issue Jan 13, 2017 · 48 comments
Closed

build 生产环境不支持 hash文件名吗? #69

Superman-wc opened this issue Jan 13, 2017 · 48 comments
Milestone

Comments

@Superman-wc
Copy link

看了一下config 中的文件, 生产环境中不支持 hash 文件名啊,,希望赶紧支持起来哦!

@sorrycc
Copy link
Owner

sorrycc commented Jan 13, 2017

好,下个版本。

@Superman-wc
Copy link
Author

如果可以的话, 支持hash 后,在build 后 集成 处理html文件中对js,css文件引用的路径修改,以前使用atool-build 时,都是用gulp 处理,,感觉只是光有hash还是很不完美的!

@sorrycc
Copy link
Owner

sorrycc commented Jan 14, 2017

@shenqihui
Copy link

+1

3 similar comments
@se1phine
Copy link

+1

@zzwzzhao
Copy link

+1

@rendongsc
Copy link

+1

@mdluo
Copy link

mdluo commented May 3, 2017

Workaround:

思路

  • 使用 webpack output 来给 js 文件加 hash
  • 使用插件 extract-text-webpack-plugin 来给 css 文件加 hash
  • 使用插件 html-webpack-plugin 来自动根据
    webpack 加的 hash 来引入对应的 css 和 js 并生成 html 文件
  • 使用插件 webpack-chunk-hash 来覆盖 webpack 的默认计算 hash 的方式,使用文件内容的 md5 来生成 chunkhash,避免分布式部署的时候生成文件名不一致

安装

npm i -D ejs-loader html-webpack-plugin webpack-chunk-hash

无需安装 extract-text-webpack-plugin 因为 roadhog 已经带了 1.0.1 版,如果自己安装了 2.x 版反而可能出问题。需要额外安装 ejs-loader 因为 webpack 配置里会用到

webpack.config.js

const fs = require('fs')

const ExtractTextPlugin = require('extract-text-webpack-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const WebpackChunkHash = require('webpack-chunk-hash')

module.exports = function (config, env) {
  config.module.loaders[0].exclude.push(/\.ejs$/)    // 注 1
  if (env === 'production') {
    config.output.filename = '[name].[chunkhash].js'
    config.output.chunkFilename = '[chunkhash].async.js'
    config.plugins[3] = new ExtractTextPlugin('[contenthash:20].css')    // 注 2
    config.plugins.push(
      new HtmlWebpackPlugin({
        template: 'ejs!src/index.ejs',    // 注 3
        inject: true,
        minify: { collapseWhitespace: true },
        production: true,
      }),
      new WebpackChunkHash({ algorithm: 'md5' })
    )
  } else {
    config.plugins.push(
      new HtmlWebpackPlugin({
        template: 'ejs!src/index.ejs',
        inject: true,
      }),
    )
  }
  return config
}

[1] roadhog 默认配置把非 特定格式 的文件都用 url-loader 去加载,但是 html-webpack-plugin 需要的 ejs 文件会变成 base64 编码,所以要把 ejs 格式加入 loader 白名单,参考

[2] 覆盖 roadhog 的 配置

[3] roadhog 对 html 默认用的 file-loader,这里的 html-webpack-plugin 需要读取其内容作为模板,所以换成 ejs,也就不再需要 index.html

.roadhogrc

{
  "env": {
    "production": {
      "publicPath": "https://cdn.example.com/"
    }
  }
}

index.ejs

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Example</title>
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
</head>
</head>
<body>
  <div id="root"></div>
</body>
</html>

index.js

去掉 import './index.html' (如果有的话)

结论

这样就同时兼顾了开发环境和部署环境使用同一套 html 入口,并且开发环境使用本地文件,部署环境使用按照文件内容 MD5 命名了的 CDN 文件(方便缓存控制)

参考

@varrant
Copy link

varrant commented May 5, 2017

+1

@varrant
Copy link

varrant commented May 5, 2017

@mdluo 你这个方法试过了吗?我用了一下,报错:

You may need an appropriate loader to handle this file type.

@mdluo
Copy link

mdluo commented May 5, 2017

@varrant 肯定试过啊,我目前项目里就是这样用的。你看看是不是没装 ejs-loader

@varrant
Copy link

varrant commented May 6, 2017

@mdluo 在roadhog里面装ejs-loader吗?还是全局装ejs-loader?还是在项目里面装?

@mdluo
Copy link

mdluo commented May 7, 2017

@varrant 我更新了原文,加了说明和 CDN 的配置

@varrant
Copy link

varrant commented May 7, 2017

@mdluo thanks very much ....遇到很多坑,终于成功了。cdn功能还未尝试,准备明天尝试。。
@sorrycc 不实现hash功能,是不是阿里已经有一套结合cdn的实现方式呢?
@pigcan 我看了atool-build 也并未实现hash功能,但是,我用atool-build也能构建roadhog项目,那么roadhog和atool-build是不是又一定的联系呢?
thanks

@varrant
Copy link

varrant commented May 8, 2017

@mdluo

else {
    config.plugins.push(
      new HtmlWebpackPlugin({
        template: 'ejs!src/index.ejs',
        inject: true,
      }),
    )
  }

这一句我没加,但是我在index.js中同时也引入了index.html

为什么这么做,因为我加上这句话,有问题,报错。

@mdluo
Copy link

mdluo commented May 9, 2017

我又更新了回复,因为我之前的写法有个问题, chunk 文件不会从 CDN 地址去读

现在直接用 .roadhogrc 暴露出来的配置项 publicPath 去配置 CDN 地址,直接用 HtmlWebpackPlugin 的 inject

@acmeid
Copy link

acmeid commented May 10, 2017

请问这个功能加上去了吗?
我是使用dva-cli生成的项目,假如还没有这项功能,能不能提供一个临时的解决方法?

@BurnhamZhang
Copy link

说好的下个版本呢。。。

@MrCuriosity
Copy link

说好的下个版本呢。。。
我也是学@mdluo一样去改webpack.config.js了

@wuzhuzhu
Copy link

说好的下个版本呢。。。

@chaxiaoyou
Copy link

说好的下个版本呢、。。

@ghost
Copy link

ghost commented Jul 10, 2017

有点搞不懂如果要用webpack来解决问题,为什么还要用roadhog?直接用webpack集成就好了啊

@YuriTu
Copy link

YuriTu commented Jul 18, 2017

@nick290 同感

感觉作者把webpack封装了一遍,却又砍掉了很多常用功能
按照作者所说 如果roadhog的特色是 MOCK 和HMR ,何必封死webpack的功能,
给一份配置好的默认配置文件不就结了。
带着枷锁跳舞
sad :(

@sorrycc sorrycc mentioned this issue Aug 7, 2017
@shenqihui
Copy link

v1.0.1 版本, 配置 multipage 为 true 时候会输出如下的 js 。

<script type="text/javascript" src="undefined"></script><script type="text/javascript" src="/index.js"></script>

@terminalqo
Copy link

@mdluo 请教如何在roadhog开启hash之后, 来自动根据加的 hash 来引入对应的 css 和 js 并生成 html 文件

@holynova
Copy link

@weishijun14
加入html.ejs文件, 就可以自动加入带hash的js了

@holynova
Copy link

holynova commented Aug 14, 2017

有新的问题:

打开hash功能, 加入index.ejs后, build是没问题.
但是本地调试, 也就是npm start会报错

webpack-internal:///6:1 Uncaught ReferenceError: roadhog is not defined
    at eval (webpack-internal:///6:1)
    at Object.<anonymous> (index.js:838)
    at __webpack_require__ (index.js:706)
    at fn (index.js:112)
    at eval (webpack-internal:///2:1)
    at Object.<anonymous> (index.js:818)
    at __webpack_require__ (index.js:706)
    at fn (index.js:112)
    at eval (webpack-internal:///60:12)
    at Object.<anonymous> (index.js:1145)

问题;

  1. 加入index.ejs后, index.html就完全没用了么?
  2. 本地怎么调试?

我现在的解决方法是,:

  1. 本地调试的时候, 不带index.ejs, 还是用原来的index.html, 这样也可以用0.6.0版本加入的dll功能 ,加快本地调试速度.
  2. 要上线时, 加入index.ejs, 然后npm run build

这样做好麻烦啊, 还要手动改文件,有没有更好的办法?
按照高票答案 @mdluo 的方法, 是可以兼顾本地调试和正式环境的 ,但1,0的版本怎么弄啊?

@sorrycc
Copy link
Owner

sorrycc commented Aug 14, 2017

所以,问题是 index.ejs 没有自动引入 dll 文件?

@sorrycc
Copy link
Owner

sorrycc commented Aug 14, 2017

#381,我建了个 issue 来跟进这个问题。

@acwong00
Copy link

@holynova 请问ejs文件是放在哪个目录下面?如果是多页面的话roadhogrc 如何配置?

@holynova
Copy link

holynova commented Aug 21, 2017

@acwong00
V1.1.0 release log mentioned:

支持 HtmlWebpackPlugin,基于约定,存在 src/index.ejs 即开启此功能 (#356)

so add the ejs file under src folder

@tcstory
Copy link

tcstory commented Dec 13, 2017

我也来贴贴我的配置把.

const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = function (webpackConfig, env) {
    // 我的项目里,使用了jquery
    if (!Array.isArray(webpackConfig.module.rules)) {
        webpackConfig.module.rules = [];
    }
    webpackConfig.module.rules.push({
        test: require.resolve('jquery'),
        use: [{
            loader: 'expose-loader',
            options: '$',
        }],
    });

    // 使用html-webpack-plugin来处理html文件
    webpackConfig.plugins.push(
        new HtmlWebpackPlugin({
            template: 'public/index.html',
            inject: true,
        }),
    );

    // 下面这部分代码,是把file-loader给删掉,因为我们现在用了
    // HtmlWebpackPlugin来处理html文件
    let rules = webpackConfig.module.rules;
    let idx = -1;
    for (let i = 0; i < rules.length; i++) {
        if (rules[i].test) {
            if (rules[i].test.toString() === '/\\.html$/') {
                idx = i;
            }
        }
    }
    rules.splice(idx, 1);

    if (env === 'production') {
        webpackConfig.output.publicPath = '/public/';
    } else {
        // 我发现,如果在dev环境下,设置了publicPath,那么会导致文件找不到
        // webpackConfig.output.publicPath = '/public/';
    }


    return webpackConfig;
};

我的这个配置呢,可以在build的时候让静态文件的路径加上/public前缀,不过在开发环境下,启动dev server的时候,我发现就不能再设置publicPath了,会导致静态文件找不到, 有别的什么办法可以解决这个问题吗?

@manuo123
Copy link

roadhog打包出来的index.js有720kb,马上功能迭代了肯定会越来越大,请问有压缩的方法吗,尝试了网上所说的几种配置都不行

@xiaosansiji
Copy link

@manuo123 没做 commonChunk 抽取吗?你的比较大是不是把 react/react-dom 等都打进 index 里了。如果你在用较新版本的 roadhog 的话,可以这样:

externals: {
  '@antv/data-set': 'DataSet',
  'bizcharts': 'BizCharts',
  'react': 'window.React',
},

这样这些不太变的第三方库,在入口HTML里面单独引入,每次迭代的时候基本上就只有你业务代码了所在的 chunk 了。

@manuo123
Copy link

@xiaosansiji 你好,谢谢你的解答,请问能否提供一个具体的webpack配置的demo

@xiaosansiji
Copy link

@manuo123 大概这样,更多设置还是参考 roadhog 的文档吧,我的 roadhog 版本是 2.2.0
/.webpackrc.js

const path = require('path');

export default {
  entry: 'src/index.js',
  extraBabelPlugins: [
    'transform-decorators-legacy',
    ['import', { libraryName: 'antd', libraryDirectory: 'es', style: true }],
  ],
  env: {
    development: {
      extraBabelPlugins: ['dva-hmr'],
    },
  },
  // 后期 monitor、svc 等各站点共享 cdn 内的公共 js 资源
  externals: {
    '@antv/data-set': 'DataSet',
    bizcharts: 'BizCharts',
    rollbar: 'rollbar',
  },
  alias: {
    components: path.resolve(__dirname, 'src/components/'),
    layouts: path.resolve(__dirname, 'src/layouts/'),
    utils: path.resolve(__dirname, 'src/utils/'),
  },
  ignoreMomentLocale: true,
  theme: './src/theme.js',
  html: {
    template: './src/index.ejs',
  },
  disableDynamicImport: true,
  publicPath: '/',
  hash: true,
  proxy: {
   ...
  }
};

@manuo123
Copy link

@xiaosansiji 感谢

@tang-yue
Copy link

@xiaosansiji 请问要配打包文件的目录要怎么配呢? 默认是在dist 目录下,现在我想改成在 dist/xxxx目录下。

@xiaosansiji
Copy link

@tang-yue
增加配置outputPath: 'dist/xx', 结果:
image
这是 webpack 提供的接口,详情建议看下这里

@tang-yue
Copy link

@xiaosansiji 谢谢这个问题我已经解决了。请问我现在想改变引用js的url, 现在是域名/index.js ,我想变成 域名/xxxx/index.js , 请问应该如何修改呢。我尝试修改publicPath 但是,会导致本地访问页面,出现Cannot GET 路径名 , 找不到我项目里的路径。请问你知道应该怎么改吗?

@xiaosansiji
Copy link

@tang-yue
image
用下env 配置,区分开发环境和生产环境就可以了

@tang-yue
Copy link

@xiaosansiji 十分感谢,目前项目在测试环境和本地环境都可以运行了。

@huangxiaohao
Copy link

各位大佬, 我按照你们讨论的写法如下写了,但是打包出来的文件名还是没有处理过的。配置如下:
.roadhogrc:

{
  "entry": "src/index.js",
  "hash" : true,
  "env": {
    "development": {
      "extraBabelPlugins": [
        "dva-hmr",
        "transform-runtime",
        ["import", { "libraryName": "antd", "style": "css" }]
      ]
    },
    "production": {
      "extraBabelPlugins": [
        "transform-runtime",
        ["import", { "libraryName": "antd", "style": "css" }]
      ]
    }
  }
}

已经在src下创建index.ejs的文件

package.json:

{
  "private": true,
  "scripts": {
    "start": "roadhog server",
    "build": "roadhog build",
    "lint": "eslint --ext .js src test",
    "precommit": "npm run lint"
  },
  "dependencies": {
    "antd": "^3.7.3",
    "dva": "^2.3.1",
    "rc-bmap": "^0.1.8",
    "react": "^16.2.0",
    "react-clamp-lines": "^1.1.0",
    "react-dom": "^16.2.0"
  },
  "devDependencies": {
    "babel-plugin-dva-hmr": "^0.3.2",
    "babel-plugin-import": "^1.8.0",
    "eslint": "^4.14.0",
    "eslint-config-umi": "^0.1.1",
    "eslint-plugin-flowtype": "^2.34.1",
    "eslint-plugin-import": "^2.6.0",
    "eslint-plugin-jsx-a11y": "^5.1.1",
    "eslint-plugin-react": "^7.1.0",
    "husky": "^0.12.0",
    "redbox-react": "^1.4.3",
    "roadhog": "^2.0.0"
  }
}

但是结果依旧没有进行hash,如下:
qq20180821-163009 2x

@liyan-web
Copy link

加了 src/index.ejs
修改了.webpackrc.js 的配置:

  hash: true,
  html: { "template": "./src/index.ejs" },

就能用了
当前版本 "roadhog": "^2.4.5"

@dbwcooper
Copy link

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