Open Jiiiiiin opened 6 years ago
记得之前 vue-loader 不支持 happypack,还没有研究过
大神新年好,我的项目构建也递增到 10分钟以上了,用HappyPack立马降到60s内,由于vux-loader在编译时未支持HappyPack,打包出来的文件大小有误,还请大神百忙之中抽点时间解决这个问题呢,大型项目需要您的技术支持,谢谢!
var utils = require('./utils')
var webpack = require('webpack')
var config = require('../config')
var vueLoaderConfig = require('./vue-loader.conf')
var vuxLoader = require('vux-loader')
var isProduction = process.env.NODE_ENV === 'production'
var HappyPack = require('happypack') // #优化
var os = require('os')
var happyThreadPool = HappyPack.ThreadPool({ size: os.cpus().length }) // <-
function resolve (dir) {
return path.join(__dirname, '..', dir)
}
const webpackConfig = {
entry: {
// app: './src/main.js',
app: ['babel-polyfill', './src/main.js']
},
output: {
path: config.build.assetsRoot,
filename: '[name].js',
publicPath: isProduction
? config.build.assetsPublicPath
: config.dev.assetsPublicPath
},
resolve: {
extensions: ['.js', '.vue', '.json'],
alias: {
'vue$': 'vue/dist/vue.esm.js',
'@': resolve('src'),
'assets': path.resolve(__dirname, '../src/assets'),
'comps': path.resolve(__dirname, '../src/components'),
'views': path.resolve(__dirname, '../src/views'),
'api': path.resolve(__dirname, '../src/api'),
'store': path.resolve(__dirname, '../src/store'),
'theme': isProduction
? path.resolve(__dirname, `../src/themes/${config.build.theme}`)
: path.resolve(__dirname, `../src/themes/${config.dev.env.theme}`)
}
},
module: {
rules: [
{
test: /\.(js|vue)$/,
loader: 'eslint-loader',
enforce: 'pre',
include: [resolve('src')],
options: {
formatter: require('eslint-friendly-formatter')
}
},
{
test: /\.vue$/,
loader: 'vue-loader',
// use: 'happypack/loader?id=vueLoader'
options: vueLoaderConfig
},
{
test: /\.js$/,
loader: ['babel-loader?cacheDirectory=true'], // #1优化打包速度 - 'babel-loader'
// use: 'happypack/loader?id=js',
include: [resolve('src'), resolve('test')]
},
{
test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 5000,
name: utils.assetsPath('img/[name].[hash:7].[ext]')
}
},
{
test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: utils.assetsPath('media/[name].[hash:7].[ext]')
}
},
{
test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: utils.assetsPath('fonts/[name].[hash:7].[ext]')
}
}
]
}
// plugins: [
// new HappyPack({
// id: 'vueLoader',
// threadPool: happyThreadPool,
// verbose: true,
// loaders: [{
// loader: 'vue-loader',
// options: vueLoaderConfig
// }]
// }),
// new HappyPack({
// id: 'js',
// threadPool: happyThreadPool,
// verbose: true,
// loaders: ['babel-loader?cacheDirectory=true']
// })
// ]
}
module.exports = vuxLoader.merge(webpackConfig, {
options: { showVuxVersionInfo: false },
cache: true, // #2优化
plugins: [
'vux-ui',
new webpack.optimize.CommonsChunkPlugin({ // #3优化 效果明显
async: 'shared-module',
minChunks: (module, count) => (
count >= 2 // 当一个模块被重复引用2次或以上的时候单独打包起来。
)
})
]
})```
我们的项目也是这样,一个银行app,路由组织如下,已经将近百个页面:
期望老大也往今年也往一些细节方面深入一下,不单单针对这个问题 :)
@fxjs 可以试试dll 也可以优化一些。
现在我只能是在dev模式下开启happy,vue-loader直接使用happy我的项目会出现问题,我只是把涉及js的处理进行了处理,效果还可以,针对生产打包的时候还是没有使用:
'use strict'
const path = require('path')
const utils = require('./utils')
const config = require('../config')
const vueLoaderConfig = require('./vue-loader.conf')
const HappyPack = require('happypack')
const os = require('os')
const happyThreadPool = HappyPack.ThreadPool({size: os.cpus().length})
const merge = require('webpack-merge')
function resolve(dir) {
return path.join(__dirname, '..', dir)
}
const createLintingRule = () => ({
test: /\.(js|vue)$/,
loader: 'eslint-loader',
enforce: 'pre',
include: [resolve('src'), resolve('test')],
options: {
formatter: require('eslint-friendly-formatter'),
emitWarning: !config.dev.showEslintErrorsInOverlay
}
})
console.log('process.env.NODE_ENV', process.env.NODE_ENV === 'production')
// 解决vux-loader不支持的问题 https://github.com/airyland/vux/issues/2492
const createVueLoaderOptions = () => {
if(process.env.NODE_ENV === 'production'){
return vueLoaderConfig
} else {
return {...vueLoaderConfig,
loaders: {
js: 'happypack/loader?id=js'
}
}
}
}
const createJsLoaders = () => {
if(process.env.NODE_ENV === 'production'){
return 'babel-loader'
} else {
return ['happypack/loader?id=js']
}
}
const webpackConfig = {
context: path.resolve(__dirname, '../'),
entry: {
app: './src/main.js'
},
output: {
path: config.build.assetsRoot,
filename: '[name].js',
chunkFilename: '[name].js',
publicPath: process.env.NODE_ENV === 'production'
? config.build.assetsPublicPath
: config.dev.assetsPublicPath
},
resolve: {
extensions: ['.js', '.vue', '.json', '.less', '.styl'],
alias: {
'@': resolve('src'),
'@assets': resolve('src/assets'),
'@api': resolve('src/api'),
'@transcode-types': resolve('src/api/transcode-types.js'),
'@mutation-types': resolve('src/store/mutation-types.js'),
'@styl': resolve('src/assets/styl'),
'@comp': resolve('src/components'),
'@ccomp': resolve('src/base/comm'),
'@bcomp': resolve('src/base/business'),
'@store': resolve('src/store')
}
},
module: {
rules: [
...(config.dev.useEslint ? [createLintingRule()] : []),
{
test: /\.vue$/,
loader: 'vue-loader',
options: createVueLoaderOptions(),
},
{
test: /\.js$/,
loader: createJsLoaders(),
include: [resolve('src'), resolve('test'), resolve('node_modules/vue-echarts-v3/src'), resolve('node_modules/webpack-dev-server/client'), resolve('node_modules/vue-viewplus/src/')]
},
{
test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: utils.assetsPath('img/[name].[hash:7].[ext]')
}
},
{
test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: utils.assetsPath('media/[name].[hash:7].[ext]')
}
},
{
test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: utils.assetsPath('fonts/[name].[hash:7].[ext]')
}
}
]
},
plugins: [
...(process.env.NODE_ENV === 'production' ? []: [new HappyPack({
id: 'js',
loaders: ['babel-loader?cacheDirectory=true'],
threadPool: happyThreadPool
})]),
],
node: {
// prevent webpack from injecting useless setImmediate polyfill because Vue
// source contains it (although only uses it if it's native).
setImmediate: false,
// prevent webpack from injecting mocks to Node native modules
// that does not make sense for the client
dgram: 'empty',
fs: 'empty',
net: 'empty',
tls: 'empty',
child_process: 'empty'
}
}
const vuxLoader = require('vux-loader')
const vuxConfig = require('./vux-config')
module.exports = vuxLoader.merge(webpackConfig, vuxConfig)
近期研究一下。目前自己的使用一直是推送后服务器自动构建,因此在构建时间方面没有太大感觉。
@airyland 某些企业的老系统架构,你懂得,根本不允许搞自动化集成,自己的机器性能就到那了,这一块对我们这种应用还是有很大需求,当然这不能说是vux需要做的工作; 感谢!
问题解决了,根源是多处引入了 'router' 导致router实例N次引起,实例router非常耗时!!目前降到了150s-
@fxjs 你解决了吗?跟路由有关系???? 我的情况和你的差不多。happypack就对vue和js用了、原先本地10分钟,现在26秒。打包出来的文件全是null,文件连1kb都没有
能请问你怎么解决的吗?大神,求助,搞了一周了。我们的项目也是非常大
@chengzi1222 1、排查代码是否有多处 import router .. ;2、使用dll抽取公共库如vue、axios、lodash等
@fxjs , import router .只有两处,dll抽取公共库已经做过了。。。。现在就是尝试多线程,happypack对vue-loader,好像不能解析, @Jiiiiiin 请问,你的happypack'对vue-loader用起了吗?
@chengzi1222 还等着作者修复呢 哈哈
目前上面的配置只能用于dev模式,prod还不支持
@chengzi1222 你好 请问你dll.config是怎么配置的,我抽取vux的时候报一对错,主要是以下两种
@ron0115 请问你的 dll 成功了吗 我的也报这些错误
@airyland vux贡献者们 新年好~。~
因为业务代码太多,打包时间已经递增到9分钟,尝试了一下happypack,降低了很多,但是发现,vux-loader就没能干预构建过程,导致使用了未进行[按需引入]的版本。
相同模块使用happypack的效果:
function resolve(dir) { return path.join(__dirname, '..', dir) }
const createLintingRule = () => ({ test: /.(js|vue)$/, loader: 'eslint-loader', enforce: 'pre', include: [resolve('src'), resolve('test')], options: { formatter: require('eslint-friendly-formatter'), emitWarning: !config.dev.showEslintErrorsInOverlay } })
const webpackConfig = { context: path.resolve(__dirname, '../'), entry: { app: './src/main.js' }, output: { path: config.build.assetsRoot, filename: '[name].js', chunkFilename: '[name].js', publicPath: process.env.NODE_ENV === 'production' ? config.build.assetsPublicPath : config.dev.assetsPublicPath }, resolve: { extensions: ['.js', '.vue', '.json', '.less', '.styl'], alias: { '@': resolve('src'), '@assets': resolve('src/assets'), '@api': resolve('src/api'), '@transcode-types': resolve('src/api/transcode-types.js'), '@mutation-types': resolve('src/store/mutation-types.js'), '@styl': resolve('src/assets/styl'), '@comp': resolve('src/components'), '@ccomp': resolve('src/base/comm'), '@bcomp': resolve('src/base/business'), '@store': resolve('src/store') } }, module: { rules: [ ...(config.dev.useEslint ? [createLintingRule()] : []), { test: /.vue$/, loader: 'vue-loader', options: vueLoaderConfig // options: {...vueLoaderConfig, // loaders: { // js: 'happypack/loader?id=js' // } // }, }, { test: /.js$/, loader: 'babel-loader', // loader: ['happypack/loader?id=js'], include: [resolve('src'), resolve('test'), resolve('node_modules/vue-echarts-v3/src'), resolve('node_modules/webpack-dev-server/client'), resolve('node_modules/vue-viewplus/src/')] }, //... }, // plugins: [ // new HappyPack({ // id: 'js', // loaders: ['babel-loader?cacheDirectory=true'], // threadPool: happyThreadPool // }) // ], node: { // prevent webpack from injecting useless setImmediate polyfill because Vue // source contains it (although only uses it if it's native). setImmediate: false, // prevent webpack from injecting mocks to Node native modules // that does not make sense for the client dgram: 'empty', fs: 'empty', net: 'empty', tls: 'empty', child_process: 'empty' } }
const vuxLoader = require('vux-loader') const vuxConfig = require('./vux-config') module.exports = vuxLoader.merge(webpackConfig, vuxConfig)