UNPKG

chameleon-tool

Version:

chameleon 脚手架工具

275 lines (255 loc) 7.63 kB
const path = require('path'); const webpack = require('webpack'); const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin; const { getBabelPath, getGlobalCheckWhiteList, styleLoaders, getWebEntry } = require('../utils'); var ExtractTextPlugin = require('cml-extract-css-webpack-plugin') var UglifyJsPlugin = require('uglifyjs-webpack-plugin') var OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin') const ChameleonWebpackPlugin = require('chameleon-webpack-plugin') const WebpackCheckPlugin = require('webpack-check-plugin') const getCmlLoaderConfig = require('../cml-loader.conf'); const ExportPlugin = require('./exportPlugin'); const CleanWebpackPlugin = require('clean-webpack-plugin'); module.exports = function (options) { let { type, media, root, disableExtract, mode } = options; function getstaticPath(filetype) { return options.hash ? `static/${filetype}/[name]_[hash:7].[ext]` : `static/${filetype}/[name].[ext]`; } function getJsPath() { return options.hash ? '[name]_[chunkhash].js' : '[name].js' } // 组件导出路径 let outputPath = options.outputPath || path.resolve(root, 'dist/export/web'); // 资源公共路径 let publicPath; if (mode === 'production' && !options.publicPath) { throw new Error('导出生产环境模式组件必须设置publicPath') } publicPath = options.publicPath || '/'; var cmlLoaders = [{ loader: 'cml-vue-loader', options: Object.assign(getCmlLoaderConfig({ type: 'web', disableExtract, media, mode }), { postcss: { config: { path: path.join(cml.root, './configs/postcss/web/.postcssrc.js') } }, compilerModules: [ { postTransformNode: el => { // to convert vnode for weex components. require('chameleon-vue-precompiler')()(el) } } ] }) }, { loader: path.resolve(__dirname, './export-loader.js'), options: { mode } }, { loader: 'chameleon-loader', options: { ...getCmlLoaderConfig({ type: 'web', disableExtract }), cmlType: 'web', media, check: cml.config.get().check, postcssMixins: cml.config.get().cmss // 传递给模板编译,处理web端内置style } } ] let { entry } = getWebEntry(options); let commonConfig = { context: path.resolve(root), entry, output: { path: outputPath, publicPath, libraryTarget: "umd", filename: getJsPath() }, resolve: { extensions: ['.cml', '.interface', '.vue', '.js'], alias: { '$ROUTER': path.resolve(root, '.temp/router.js') }, modules: [ path.join(root, '/node_modules'), path.join(cml.root, '/node_modules') ] }, resolveLoader: { modules: [ path.join(root, '/node_modules'), path.join(cml.root, '/node_modules') ] }, module: { rules: [ { test: /\.js$/, exclude: /(\.min\.js)/, // exclude: /(node_modules|bower_components)/, // 不能babel babel-runtime include: getBabelPath(), use: [{ loader: 'babel-loader', options: { 'filename': path.join(cml.root, 'package.json') } }, { loader: path.resolve(__dirname, './export-loader.js'), options: { mode } } ] }, { test: /\.(png|jpe?g|gif|svg)(\?.*)?$/, use: [ { loader: 'chameleon-url-loader', options: { name: getstaticPath('img'), fallback: mode === 'production' ? undefined : path.resolve(__dirname, './export-loader.js'), fileType: 'assets', mode } } ] }, { test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/, loader: 'file-loader', options: { name: getstaticPath('media'), useRelativePath: mode !== 'production', outputPath: function(url) { return mode === 'production' ? url : url + '?__export'; } } }, { test: /\.(woff|woff2?|eot|ttf|otf)(\?.*)?$/, loader: 'file-loader', options: { name: getstaticPath('fonts'), useRelativePath: mode !== 'production', outputPath: function(url) { return mode === 'production' ? url : url + '?__export'; } } }, { test: /\.interface$/, // 不能babel babel-runtime include: getBabelPath(), use: [{ loader: 'babel-loader', options: { 'filename': path.join(cml.root, 'package.json') } }, { loader: 'interface-loader', options: { cmlType: type } }, { loader: path.resolve(__dirname, './export-loader.js'), options: { mode } } ] }, ...styleLoaders({ type: 'web', extract: false, media }), { test: /\.cml$/, use: cmlLoaders }, { test: /\.vue$/, use: [{ loader: 'cml-vue-loader', options: Object.assign(getCmlLoaderConfig({ type: 'web', disableExtract }), { postcss: { config: { path: path.join(cml.root, './configs/postcss/web/.postcssrc.js') } }, compilerModules: [ { postTransformNode: el => { require('chameleon-vue-precompiler')()(el) } } ] }) } ] } ] }, plugins: [ new webpack.DefinePlugin({ 'process.env.platform': JSON.stringify(type) }), new ExportPlugin({exportType: 'web', mode}), new CleanWebpackPlugin(['./*'], {root: outputPath, verbose: false}) ] } if (cml.config.get().enableGlobalCheck === true) { commonConfig.plugins.push( new WebpackCheckPlugin({ cmlType: type, whiteListFile: getGlobalCheckWhiteList() }) ) } if (options.definePlugin) { commonConfig.plugins.push(new webpack.DefinePlugin(options.definePlugin)) } if (options.analysis) { commonConfig.plugins.push(new BundleAnalyzerPlugin()) } if (options.minimize) { commonConfig.plugins = commonConfig.plugins.concat([ new OptimizeCSSPlugin({ assetNameRegExp: /\.css$/, cssProcessorOptions: { safe: true, discardComments: { removeAll: true }, autoprefixer: false } }), new UglifyJsPlugin({}) ]) } let moduleIdType = options.moduleIdType let moduleIdMap = { hash: new webpack.HashedModuleIdsPlugin(), name: new webpack.NamedModulesPlugin(), chameleon: new ChameleonWebpackPlugin({ openModuleHash: true, openChunkHash: true }) } if (moduleIdType && moduleIdMap[moduleIdType]) { commonConfig.plugins.push(moduleIdMap[moduleIdType]) } if (disableExtract !== true || mode !== 'production') { commonConfig.plugins.push( new ExtractTextPlugin({ filename: options.hash ? 'static/css/[name]_[contenthash].css' : 'static/css/[name].css', allChunks: true }) ) } return commonConfig; }