团队正在做OA前端项目(ElementUI全组件入口JS文件引入),项目前端功能模块组件太多,采用Webpack Vue2 multiple entry 多页面入口方式开发,开发调试运行正常,每个入口Html都是相同的布局导航主界面框架(延迟加载各自相关的组件模块)Webpack打包时想抽离出ElementUI(JS/CSS)做直接CDN引入,JS可以通过配置 externals: { 'element-ui':'ElementUI'}排除,但是CSS文件还是写入到了每个入口页面各自独立的CSS文件,请支招...
配置环境
Webpack ^2.2.1
Vue ^2.2.2
ElementUI ^1.2.5
webpack.base.conf
var path = require('path')
var webpack = require('webpack')
var config = require('../config')
var utils = require('./utils')
var entris = require('./entris')
var projectRoot = path.resolve(__dirname, '../')
var env = process.env.NODE_ENV
// check env & config/index.js to decide weither to enable CSS Sourcemaps for the
// various preprocessor loaders added to vue-loader at the end of this file
var cssSourceMapDev = (env === 'development' && config.dev.cssSourceMap)
var cssSourceMapProd = (env === 'production' && config.build.productionSourceMap)
var useCssSourceMap = cssSourceMapDev || cssSourceMapProd
var ExtractTextPlugin = require('extract-text-webpack-plugin')
var baseWebpackConfig = {
entry: {
vendor: ['vue','vuex','vue-router']
},
output: {
path: config.build.assetsRoot,
publicPath: process.env.NODE_ENV === 'production'
? config.build.assetsPublicPath
: config.dev.assetsPublicPath,
filename: 'js/[name].js'
},
externals: {
'element-ui':'ElementUI'
},
resolve: {
extensions: ['.js', '.vue'],/* require时省略的扩展名,如:require('module') 不需要module.js*/
modules: [
path.join(__dirname, '../node_modules'),
],
alias: {
'~src': path.resolve(__dirname, '../src'),
'~api': path.resolve(__dirname, '../src/api/index'),
'~api-config': path.resolve(__dirname, '../src/api/config'),
'~components': path.resolve(__dirname, '../src/components'),
'~pages': path.resolve(__dirname, '../src/pages'),
'~store': path.resolve(__dirname, '../src/store'),
'~utils': path.resolve(__dirname, '../src/utils')
}
},
resolveLoader: {
modules: [path.join(__dirname, '../node_modules')]
},
module: {
rules: [
{
test: /\.vue$/,
loader: 'eslint-loader',
enforce: "pre",
include: projectRoot,
exclude: /node_modules/
}, {
test: /\.js$/,
loader: 'eslint-loader',
enforce: "pre",
include: projectRoot,
exclude: /node_modules/
}, {
test: /\.vue$/,
loader: 'vue-loader'
}, {
test: /\.js$/,
loader: 'babel-loader',
include: projectRoot,
exclude: /node_modules/
}, {
test: /\.json$/,
loader: 'json-loader'
}, {
test: /\.html$/,
loader: 'vue-html-loader'
}, {
test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
loader: 'url-loader',
query: {
limit: 10000,
name: utils.assetsPath('img/[name].[hash:7].[ext]')
}
}, {
test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
loader: 'url-loader',
query: {
limit: 10000,
name: utils.assetsPath('css/fonts/[name].[hash:7].[ext]')
}
}
]
},
plugins: [
new webpack.ProvidePlugin({$: 'jquery', jQuery: 'jquery', 'window.jQuery': 'jquery'}),
new ExtractTextPlugin(utils.assetsPath('css/[name].css?[contenthash:7]'))
]
}
baseWebpackConfig.entry = Object.assign(baseWebpackConfig.entry, entris)
module.exports = baseWebpackConfig
webpack.prod.conf
var path = require("path")
var config = require('../config')
var utils = require('./utils')
var entris = require('./entris')
var webpack = require('webpack')
var merge = require('webpack-merge')
var baseWebpackConfig = require('./webpack.base.conf')
var ExtractTextPlugin = require('extract-text-webpack-plugin')
var HtmlWebpackPlugin = require('html-webpack-plugin')
config.build.productionSourceMap = false
baseWebpackConfig = merge(baseWebpackConfig, {
module: {
rules: utils.styleLoaders({sourceMap: config.build.productionSourceMap, extract: true})
},
devtool: config.build.productionSourceMap
? '#source-map'
: false,
output: {
path: config.build.assetsRoot,
filename: utils.assetsPath('js/[name].js?[chunkhash:7]'),
chunkFilename: utils.assetsPath('js/[id].js?[chunkhash:7]')
},
plugins: [
new webpack.DefinePlugin({
'process.env': {
NODE_ENV: '"production"'
}
}),
new webpack.optimize.CommonsChunkPlugin({
name: 'vendor',
minChunks: function(module, count) {
return (module.resource && /\.js$/.test(module.resource) && module.resource.indexOf(path.join(__dirname, '../node_modules')) === 0)
}
}),
new webpack.optimize.CommonsChunkPlugin({name: 'manifest', chunks: ['vendor']}),
new webpack.optimize.UglifyJsPlugin({
compress: {
warnings: false
}
}),
new ExtractTextPlugin(utils.assetsPath('css/[name].css?[contenthash:7]')),
new webpack.LoaderOptionsPlugin({
minimize: true,
options: {
context: __dirname,
vue: {
loaders: utils.cssLoaders({sourceMap: config.build.productionSourceMap, extract: true})
}
}
})
]
})
Object.keys(entris).forEach(function(entry) {
baseWebpackConfig.plugins.push(new HtmlWebpackPlugin({
chunks: [ 'manifest', 'vendor', entry ],
filename: entry + '.html',
template: 'src/template/index.html',
inject: true,
minify: {
removeComments: true,
collapseWhitespace: true,
removeAttributeQuotes: true
}
}))
})
module.exports = baseWebpackConfig
utils.js
var path = require('path')
var config = require('../config')
var ExtractTextPlugin = require('extract-text-webpack-plugin')
exports.assetsPath = function(_path) {
var assetsSubDirectory = process.env.NODE_ENV === 'production' ? config.build.assetsSubDirectory : config.dev.assetsSubDirectory
return path.posix.join(assetsSubDirectory, _path)
}
exports.cssLoaders = function(options) {
options = options || {}
// generate loader string to be used with extract text plugin
function generateLoaders(loaders) {
loaders = ['css', 'postcss'].concat(loaders)
var sourceLoader = loaders.map(function(loader) {
var extraParamChar
if (/\?/.test(loader)) {
loader = loader.replace(/\?/, '-loader?')
extraParamChar = '&'
} else {
loader = loader + '-loader'
extraParamChar = '?'
}
return loader + (options.sourceMap ? extraParamChar + 'sourceMap' : '')
}).join('!')
if (options.extract) {
return ExtractTextPlugin.extract({ fallback: 'vue-style-loader', use: sourceLoader })
} else {
return ['vue-style-loader', sourceLoader].join('!')
}
}
// http://vuejs.github.io/vue-loader/configurations/extract-css.html
return {
css: generateLoaders([]),
postcss: generateLoaders([]),
less: generateLoaders(['less']),
sass: generateLoaders(['sass?indentedSyntax']),
scss: generateLoaders(['sass'])
}
}
// Generate loaders for standalone style files (outside of .vue)
exports.styleLoaders = function(options) {
var output = []
var loaders = exports.cssLoaders(options)
for (var extension in loaders) {
var loader = loaders[extension]
output.push({
test: new RegExp('\\.' + extension + '$'),
loader: loader
})
}
return output
}