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

支持 vendor 的配置 #370

Open
MinJieLiu opened this issue Aug 9, 2017 · 20 comments
Open

支持 vendor 的配置 #370

MinJieLiu opened this issue Aug 9, 2017 · 20 comments

Comments

@MinJieLiu
Copy link

在大多数情况下,我们需要安装一些第三方库,比如 momentclassnamesreact-helmet 等。

目前,每个异步模块只要 import了这些库,就会单独打包到这些模块中。就会导致每个模块的 js 体积过大,极端情况一个简单的模块的体积都可以超过 index.js😱。

所以 CommonsChunkPlugin 提取公共的库到 vendor.js 中还是很有必要的。

测试一些常用的库:

webpackConfig.entry.vendor = [
  'classnames',
  'moment',
  'react-helmet',
  'styled-components',
];

vendor.js 的体积是 gzip: 81.64kb

@Restry
Copy link

Restry commented Aug 9, 2017

直接用externals弄出来可以吗?
不过顺便问一句你们用externals成功过吗?我到.roadhogrc.js里面加了后和没加没区别,生成的文件和大小都一样。。。。

@MinJieLiu
Copy link
Author

@Restry externals 和 chunk 是两个概念

@xfields
Copy link

xfields commented Aug 10, 2017

+1

@sorrycc
Copy link
Owner

sorrycc commented Aug 11, 2017

不过顺便问一句你们用externals成功过吗?我到.roadhogrc.js里面加了后和没加没区别,生成的文件和大小都一样。。。。

externals 肯定是有效的,有用例。

@sorrycc
Copy link
Owner

sorrycc commented Aug 11, 2017

@MinJieLiu vendor 的配置方式有建议的吗?可以提个 PR 试试。

@MinJieLiu
Copy link
Author

MinJieLiu commented Aug 11, 2017

webpack 介绍:这种方式比较常见于,只有一个入口起点(不包括 vendor)的单页应用程序(single page application)中。

我的思路是这样:

  1. roadhog :src/config/webpack.config.prod.js 中把 CommonsChunkPlugin 插件准备好。

  2. .roadhogrcentry 可配置为 plainObject 的形式。

如:

{
  "entry": {
    "app": "./src/index.js",
    "vendors": [
      "classnames",
      "moment"
    ]
  }
}

没实践过多页应用,只有单页的思路😂

webpack 可能会移除该插件

  • 为了支持提供更佳 vendor 分离能力的 DllPlugin,考虑移除该场景。

@sorrycc
Copy link
Owner

sorrycc commented Aug 11, 2017

webpack 可能会移除该插件

哪里有说?

@MinJieLiu
Copy link
Author

@sorrycc
Copy link
Owner

sorrycc commented Aug 11, 2017

https://webpack.js.org/configuration/entry-context/
官方文档上好像并没有说,感觉 dll 和 commonplugin 的作用还是不一样的。

@sorrycc sorrycc changed the title 可以考虑导出 CommonsChunkPlugin 配置 支持 vendor 的配置 Aug 11, 2017
@lengjing
Copy link

new webpack.optimize.CommonsChunkPlugin({
      name: 'vendor',
      minChunks: function (module, count) {
        // any required modules inside node_modules are extracted to vendor
        return (
          module.resource &&
          /\.js$/.test(module.resource) &&
          module.resource.indexOf('node_modules') === 0
        )
      }
    })

这样写可以不需要提前知道你引用了那些第三方库吧

@cnchore
Copy link

cnchore commented Aug 22, 2017

确实很需要提取公共库

@Runtu4378
Copy link

Runtu4378 commented Sep 7, 2017

大家可以参考一下我提取公共模块的实现

antd 模块的单独提取可以参考这个代码:

// webpack.config.js
const webpack = require('webpack')

module.exports = function wp(webpackConfig, env) {
  // 对roadhog默认配置进行操作,比如:
  if (env === 'production') {
    // 上线环境使用分包打包方式  
    webpackConfig.entry = {
      index: './src/index.js',
      vendor: [
        'moment',
        'mockjs',
        'lodash',
        'react',
        'react-dom',
        'react-helmet',
      ],
      antd: [
        'antd/lib/button',
        'antd/lib/icon',
        'antd/lib/table',
        'antd/lib/date-picker',
        'antd/lib/form',
        'antd/lib/modal',
        'antd/lib/grid',
        'antd/lib/input',
      ],
    }
    webpackConfig.plugins.push(new webpack.optimize.CommonsChunkPlugin({
      name: ['vendor', 'antd'],
      minChunks: Infinity,
    }))
  }

  return webpackConfig
}

上面是根目录下 webpack.config.js 文件的内容,在正式环境时候会进行分包打包

下面是一些注意事项:

  • src/index.js 的内容最好为下面这样的
// src/index.js
import 'babel-polyfill'
import dva from 'dva'
import createHistory from 'history/createBrowserHistory'
import createLoading from 'dva-loading'
import { message } from 'antd'
import moment from 'moment'
import 'moment/locale/zh-cn'
import './index.less'
import './themes/index.less'

moment.locale('zh-cn')
const ERROR_MSG_DURATION = 3 // 3 秒

// 1. Initialize
const app = dva({
  history: createHistory(),
  onError(error) {
    console.error(error)
    message.error(error.message, ERROR_MSG_DURATION)
  },
})

// 2. Plugins
app.use(createLoading({ effects: true }))

// 3. Model
app.model(require('./models/app'))
app.model(require('./models/login'))
app.model(require('./models/page'))
app.model(require('./models/utils'))
app.model(require('./models/query'))

// 4. Router
app.router(require('./router'))

// 5. Start
app.start('#root')

不需要引用 index,html 改为自动引用 index.ejs

src
|-index.js
|-index,ejs
|-index.less
|-router.js

  • index.ejs的内容为
// index.ejs
<!DOCTYPE html>
<html lang="zh-cn">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
</head>
<body>
<div id="root"></div>
</body>
</html>
  • 按照上面步骤的话,在生产环境会自动在 index.ejs 生成的html文件中引用入口文件 index.js;在正式环境会自动引用 antd.jsvendor.jsindex.js 这三个入口文件

ant-design#1526

@afc163
Copy link
Contributor

afc163 commented Oct 29, 2017

+1

@hopperhuang
Copy link

继续跟进一下这个issue,提取vendor公共模块·的功能实现了没有?如果实现了的话,请问有用例吗?

@imshenyz
Copy link

+1

@Runtu4378
Copy link

@imshenyz @hopperhuang 参考一下上面我更新了的答案 有问题再@我

@xiaosongxiaosong
Copy link

+1

@520Yanxiaofei
Copy link

@Runtu4378 你好,我按照你这个配置完了之后,就出现这个问题
image
image

image
这配置还有什么问题吗?

@gleams
Copy link

gleams commented Aug 1, 2019

.webpackrc.js中是支持vendor,配置的,而且通过分析工具也看到提取成功了。
需要另一个配置才会生效。commons我查看源码发现的,
所以正确配置应该是这样的

const packagejson = require('./package.json');
  // 省略其它配置
  entry: {
    index:'./src/index.js',
    vendor:Object.keys(packagejson.dependencies).filter((v)=>{
      if(v !=="@antv/data-set"){
        return v
      }
    })
  },
  commons:[{
    name: 'vendor',
    filename: '[name].js'
  }],

@gleams
Copy link

gleams commented Aug 1, 2019

Failed to minify the bundle. Error: vendor.js from UglifyJs
但这样处理后,会报以下错误,不知道怎么处理了,在dev下不会报错。

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