import { NuxtConfig } from '@nuxt/types'; import lodash from 'lodash'; import MomentLocalesPlugin from 'moment-locales-webpack-plugin'; import path from 'path'; import { EnumMamba } from './enum'; const isProduction = lodash.eq(process.env.NODE_ENV, 'production') const defaultBuild = { corejs: 3, extractCSS: isProduction, cache: true, splitChunks: { layouts: false, commons: true, pages: true, }, analyze: { openAnalyzer: true, analyzerMode: lodash.get({ development: 'disabled', production: 'static' }, process.env.NODE_ENV), }, } function getName() { try { const packagePath = path.join(process.cwd(), 'package.json') const { name, version } = require(packagePath); return lodash.snakeCase(lodash.join([name, version], '_')) } catch (error) { return 'nuxt' } } export function extendbuild(nuxtConfig: NuxtConfig) { const iconAlias = lodash.get(nuxtConfig, EnumMamba.iconAlias) const themePath = lodash.get(nuxtConfig, EnumMamba.themePath) const env = lodash.get(nuxtConfig, EnumMamba.envPath) const drop_console = lodash.get(nuxtConfig, EnumMamba.drop_console, false) const build = lodash.merge({ plugins: [], babel: { plugins: [] } }, lodash.assign( defaultBuild, nuxtConfig.build, lodash.pick(defaultBuild, 'analyze') )) const { extend } = build; const { scripts, externals, logs } = assignExternals(nuxtConfig); // cdn lodash.set(nuxtConfig, 'head.script', lodash.compact(lodash.concat( lodash.get(nuxtConfig, 'head.script', []), scripts ))); // 去除日志 https://github.com/terser/terser#compress-options lodash.set(build, 'terser.terserOptions.compress.drop_console', drop_console); // webpack build.extend = (config, ctx) => { lodash.map(logs, x => console.log(x)); console.log("LENG ~ env", env); config.devtool = config.devtool || 'source-map'; config.externals = lodash.assign(externals, config.externals) config.output = lodash.merge(config.output, { jsonpFunction: lodash.snakeCase('webpackjson_' + getName()), }); config.resolve.modules = lodash.concat([path.join(process.cwd(), 'node_modules')], config.resolve.modules); if (iconAlias) { lodash.set(config, 'resolve.alias["@ant-design/icons/lib/dist$"]', path.join(process.cwd(), iconAlias)) } // css 不懒加载 if (build.extractCSS) { const recursiveIssuer = function (m) { if (m.issuer) { return recursiveIssuer(m.issuer); } else if (m.name) { return m.name; } else { return false; } } // css 打一个包 https://github.com/vuejs/vue-cli/issues/2843 lodash.update(config, 'optimization.splitChunks', splitChunks => { return lodash.merge(splitChunks, { cacheGroups: { styles: { name: 'styles', // test: /\.(css|less|scss|sass|vue)$/, test: (m, c, entry = 'app') => m.constructor.name === 'CssModule' && recursiveIssuer(m) === entry, // test: /\.(css|less|vue\?vue&type=style.*&)$/, // test(module) { // if (/\.(css|less|vue)$/.test(module.resource)) { // console.log("LENG ~ module", module.resource, module.type) // return true // } // return false // }, chunks: 'all', enforce: true, } }, }) }) } lodash.isFunction(extend) && extend(config, ctx); } // 主题文件 if (themePath) { lodash.set(build, 'loaders.less.lessOptions', { // modifyVars: modifyVars, modifyVars: { // 或者可以通过 less 文件覆盖(文件路径为绝对路径) hack: `true; @import "${path.join(process.cwd(), themePath)}";`, }, javascriptEnabled: true }) } // webpack 插件 lodash.update(build, 'plugins', plugins => lodash.concat([new MomentLocalesPlugin({ localesToKeep: ['es-us', 'zh-cn'] })], plugins)) lodash.update(build, 'babel.plugins', plugins => lodash.concat([ 'lodash', ['import', { libraryName: 'ant-design-vue', libraryDirectory: 'es', style: (name) => `${name}/style/index.js` }], ['@babel/plugin-proposal-private-property-in-object', { loose: true }] ], plugins)) return build } interface IcdnConfig { /** cdn 指向的 文件 */ entry: string | Array /** 全局变量的名称 */ global: string /** 文件目录 默认是 module 名称 */ directory?: string // /** 扩展的 js */ // extends?: Array } function assignExternals(nuxtConfig: NuxtConfig) { const exls = lodash.get(nuxtConfig, EnumMamba.externals) const cdnDomain = lodash.get(nuxtConfig, EnumMamba.cdnDomain) const scripts = [] const logs = [] const externals = {} if (!cdnDomain) { console.warn('未配置 cdnDomain') } else { const urlReg = /^((http|ftp|https):\/\/[\w\-_]+(\.[\w\-_]+)+([\w\-\.,@?^=%&:/~\+#]*[\w\-\@?^=%&/~\+#])?)$/; lodash.map(exls, (val: IcdnConfig, key) => { try { const module = require.resolve(key) const packagePath = path.join(lodash.head(lodash.split(module, key)), key, 'package.json') const packageJson = require(packagePath) const version = lodash.get(packageJson, 'version') const entrys = lodash.isArray(val.entry) ? val.entry : [val.entry]; lodash.map(entrys, entry => { let cdn = entry; if (!urlReg.test(entry) && !lodash.startsWith(cdn, '//')) { cdn = lodash.join([cdnDomain, val.directory || key, version, lodash.trim(entry, '/')], '/'); } scripts.push({ src: cdn }); logs.push(`[ ${key} ] -> ${cdn}`) }) lodash.set(externals, key, val.global || key); } catch (error) { console.warn('未安装:', key) } // 获取配置中的 global 如果没有则直接使用 key // lodash.set(defaultConfig.externals, key, lodash.get(val, 'global', key)) }) } return { logs, scripts, externals } }