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 构建 Vue 项目的速度 #10

Open
lin-xin opened this issue Apr 1, 2017 · 20 comments
Open

提高 webpack 构建 Vue 项目的速度 #10

lin-xin opened this issue Apr 1, 2017 · 20 comments

Comments

@lin-xin
Copy link
Owner

lin-xin commented Apr 1, 2017

前言

最近有人给我的 Vue2 后台管理系统解决方案 提了 issue ,说执行 npm run build 构建项目的时候极其慢,然后就引起我的注意了。在项目中,引入了比较多的第三方库,导致项目大,而每次修改,都不会去修改到这些库,构建却都要再打包这些库,浪费了不少时间。所以,把这些不常变动的第三方库都提取出来,下次 build 的时候不再构建这些库,这样既可大大缩短构建时间。那么要怎么去实现呢?

解决方案

DllPlugin 和 DllReferencePlugin

查找了一下资料,发现我们可以利用 webpack 的插件 DllPlugin 和 DllReferencePlugin 来实现我们要的功能。

DllPlugin 可以把我们需要打包的第三方库打包成一个 js 文件和一个 json 文件,这个 json 文件中会映射每个打包的模块地址和 id,DllReferencePlugin 通过读取这个json文件来使用打包的这些模块。

接下来就看如何实现。

配置文件

在 build 文件夹中新建 webpack.dll.conf.js (项目基于 vue-cli 的)

const path = require('path');
const webpack = require('webpack');

module.exports = {
  entry: {
    vendor: ['vue/dist/vue.common.js','vue-router', 'babel-polyfill','axios','vue-echarts-v3']
  },
  output: {
    path: path.join(__dirname, '../static/js'),
    filename: '[name].dll.js',
    library: '[name]_library'       // vendor.dll.js中暴露出的全局变量名
  },
  plugins: [
    new webpack.DllPlugin({
      path: path.join(__dirname, '.', '[name]-manifest.json'),
      name: '[name]_library'
    }),
    new webpack.optimize.UglifyJsPlugin({
      compress: {
        warnings: false
      }
    })
  ]
};

然后在 package.json 中配置命令

"scripts": {
    ...
    "build:dll": "webpack --config build/webpack.dll.conf.js"
}

执行 npm run build:dll 命令来生成 vendor.dll.js 和 vendor-manifest.json

需要在 index.html 引入 vendor.dll.js

<body>
    <div id="app"></div>
    <script src="./static/js/vendor.dll.js"></script>
</body>

vendor-manifest.json 的内容大概如下:

{
  "name": "vendor_library",
  "content": {
    "./node_modules/core-js/modules/_export.js": {
      "id": 0,
      "meta": {}
    },
    ...
}

接下来就在 webpack.base.config.js 中通过 DLLReferencePlugin 来使用 DllPlugin 生成的 DLL Bundle

var webpack = require('webpack');

module.exports = {
    entry: {
        app: ['./src/main.js']
    },
    module: {
        ...
    }
    // 添加DllReferencePlugin插件
    plugins: [
        new webpack.DllReferencePlugin({
            context: path.resolve(__dirname, '..'),
            manifest: require('./vendor-manifest.json')
        }),
    ]
}

原先 build 需要 95446ms,配置之后执行 build 只需 14360ms,减少了 75% 的时间。

但是存在一个问题,当把太多的第三方依赖都打包到 vendor.dll.js 中去,该文件太大也会影响首屏加载时间。所以要权衡利弊,可以异步加载的插件就没有必要打包进来了,不要一味的把所有都打包到这里面来获取构建时的快感。

示例地址:vue-manage-system

个人博客:lin-xin/blog

@meidaqiao
Copy link

为什么我执行npm run build:dll报错呢, 网上说添加elementUI会报错, 我去掉了还是不行, 总是报Cannot find module

@lin-xin
Copy link
Owner Author

lin-xin commented May 19, 2017

@meitaiqiao 有问题请描述清楚!

@meidaqiao
Copy link

我按照你的步骤新建了webpack.dll.config.js,在build文件夹, package.json也添加"build:dll": "webpack --config build/webpack.dll.conf.js"
执行 npm run build:dll 命令来生成 vendor.dll.js 和 vendor-manifest.json
报下面错误:
Cannot find module '/Users/meitaiqiao/Desktop/testing/build/webpack.dll.conf.js'

@lin-xin
Copy link
Owner Author

lin-xin commented May 19, 2017

是webpack.dll.config.js的文件名写错了。应该为webpack.dll.conf.js

@meidaqiao
Copy link

额啊 , 汗颜汗颜, 没仔细看,

@lin-xin
Copy link
Owner Author

lin-xin commented May 19, 2017

@meitaiqiao 不是你的问题,是我写错了。刚改了过来

@bitqiang
Copy link

可以异步加载的插件是啥意思。是说那些不是一开始就需要加载的插件吗?
然后等到后面需要再加载吗

@lin-xin
Copy link
Owner Author

lin-xin commented Jun 30, 2017

@bitqiang 是指该插件是在某个组件里才使用的,而这个组件是通过异步的方式加载的

{
                    path: '/basetable',
                    component: resolve => require(['../components/page/BaseTable.vue'], resolve)
                },

@webfrontzhifei
Copy link

我clone了你的demo项目,在webpack.base.conf时,并没有引入DllReferencePlugin啊,去掉注释,就报错了。

@lin-xin
Copy link
Owner Author

lin-xin commented Jul 12, 2017

@webfrontzhifei index.html 里引入的 vendor.dll.js , webpack.base.config.js 中的 DLLReferencePlugin 这些注释都要去掉。

@showbestriven
Copy link

我现在run dev一次 需要60秒。 使用了 dll貌似没什么提升啊 也没报错 难道是 使用错误?

@bitqiang
Copy link

@showbestriven 可能是共用的包没有很大影响你的打包速度。
可以参考下我之前做的一些笔记,有需要的话。
http://c01c1426.wiz03.com/share/s/3071gC0CI4PR2BbWAn06uEyo2k0Tkd37d4yl2Fwo460PskRH

@aaabinbin
Copy link

aaabinbin commented Nov 7, 2017

求助大神 @lin-xin ,为啥我在vue-cli用这个dllPlugin运行的时候报,说是vue格式文件的缺少一个loader,然后同时我的vendor中已经有了element ui(包含vue结尾的文件)木有问题,就只有这个vue-quill-editor出问题了。
ERROR in ./~/vue-quill-editor/src/editor.vue
Module parse failed: E:\repo\baymax_static\node_modules\vue-quill-editor\src\editor.vue Unexpected token (1:0)
You may need an appropriate loader to handle this file type.
后来加入vue和css的loader就解决了,布吉岛为什么只有vue quill editor 有问题

@aaabinbin
Copy link

发现这里的路径 ./static/js/vendor.dll.js 如果前面加了点好像就没办法在多层路由中获取文件,去掉好像就好了

<script src="./static/js/vendor.dll.js"></script>

@SuperAL
Copy link

SuperAL commented Dec 11, 2017

@lin-xin
这样做是不是会导致打包后的文件体积变大啊?我对比了使用 dll 前后的 dist/static 文件夹的大小,发现差了 0.08 MB,使用 dll 的方式使得我打包后的 js 文件变大了。
是不是 CommonsChunkPlugin 那边我需要配置什么?

@Maplesog
Copy link

@lin-xin 当请求的路由是两层的时候,直接在当前页面刷新。这个根目录的dll文件夹会跑到路由的目录下面去。导致请求不到。请问这是该怎么更改?
65888978-da76-4765-9d95-98b8008efc31

望回复。

@yuan252525
Copy link

请问一个问题,我按照您提供的步骤操作的,基本配置都已经完成,打包时间确实比之前节省了4W毫秒,但是只要引入单独打包出来的那个js文件 放到服务器上就会报错.

@SmallBlockCat
Copy link

我的报错 Uncaught ReferenceError: bundle_library is not defined 为什么呀

@zhengtulymGh
Copy link

zhengtulymGh commented Oct 11, 2018

在html里面引用<script type="text/javascript" src="./static/js/vendor.dll.js" charset="UTF-8"></script>,使用webpack-dev-server启动的时候发现返回的是html文件怎么破?

@xyzshen
Copy link

xyzshen commented Nov 29, 2018

没有按照你的方法npm run build 是3分44秒;按照你的方法实现了一遍还是3分44秒

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