UNPKG

ae-biu

Version:

Born For AE, Born To Do

275 lines (261 loc) 7.36 kB
// @flow import path from 'path' import webpack from 'webpack' import HtmlWebpackPlugin from 'html-webpack-plugin' import CopyWebpackPlugin from 'copy-webpack-plugin' import ExtractTextPlugin from 'extract-text-webpack-plugin' import OptimizeCSSPlugin from 'optimize-css-assets-webpack-plugin' import FaviconsWebpackPlugin from 'favicons-webpack-plugin' import flat from 'flat' import crypto from 'crypto' import fs from 'fs' import logger from '../utils/logger' import getPostcssConfig from './postcss.config' import lessOptions from './less.config' import { workDir, srcDir, tplPath } from '../utils/paths' import pkg from '../utils/package' import getPolyfills from '../utils/get-polyfills' import { readDirRecursiveSync } from '../utils/read-dir-recursive' import webpackCommonConfig from './webpack.common' import { DEFAULT_LANG_MAP } from '../utils/constants' import useCDN from '../utils/use-cdn' const { ae = {} } = pkg const { languages: LANGS = DEFAULT_LANG_MAP, output: dist = 'dist', org: ORG_NAME, addHashForI18N = false } = ae const distDir = path.resolve(workDir, dist) const staticDir = path.resolve(srcDir, 'static') const modulesDir = path.resolve(srcDir, 'modules') const modulesI18NTransformer = content => JSON.stringify(flat(JSON.parse(content))) const copyPluginPatterns = [ { from: staticDir, ignore: 'locale/**/*.json' // ignore locale files, these files will be handled by below pattern }, { context: staticDir, from: 'locale/**/*.json', to: addHashForI18N ? '[path][name].[hash].[ext]' : '' }, { context: modulesDir, from: '**/*.json', to: addHashForI18N ? 'locale/[path][name].[hash].[ext]' : 'locale', transform: modulesI18NTransformer } ] console.log() const i18nHashMap = {} if (addHashForI18N) { logger.info('Create hash for i18n files\n') const staticI18nFiles = readDirRecursiveSync(staticDir, '*.json') const moduleI18nFiles = readDirRecursiveSync(modulesDir, '*.json') const files = [...staticI18nFiles, ...moduleI18nFiles] files.map(file => { let content = fs.readFileSync(file, { encoding: 'utf8' }) // modules 下面的 i18n 文件需要扁平化 if (~moduleI18nFiles.indexOf(file)) { content = modulesI18NTransformer(content) } const hash = crypto.createHash('md5') const hashSum = hash.update(content).digest('hex') const lang = path.basename(file, '.json') const scope = path.dirname(file).replace(`${modulesDir}`, '').replace(`${staticDir}/locale`, '').replace('/', '') const key = `${scope}/${lang}` i18nHashMap[key] = `${lang}.${hashSum}` }) } logger.info('Create configuration for NODE_ENV: production\n') const SDP_ENV = (process.env.SDP_ENV || 'test').trim() logger.info(`Project build for SDP_ENV: ${SDP_ENV}\n`) const polyfills = getPolyfills() // generate css loader for specific lang function getCSSLoader (lang, i18nLangs) { const loaders = [ { loader: 'style-loader' }, { loader: 'css-loader', options: { importLoaders: 1 } }, { loader: 'postcss-loader', options: getPostcssConfig(i18nLangs) } ] if (lang === 'less') { loaders.push({ loader: 'less-loader', options: lessOptions }) } return ExtractTextPlugin.extract({ fallback: loaders.shift().loader, use: loaders }) } const webpackConfig = { // current only have web target: 'web', // entry for AE entry: { app: [ ...polyfills, path.resolve(srcDir, 'index.js') ] }, output: { path: distDir, publicPath: '', filename: '[name].[chunkhash].js', chunkFilename: '[id].[chunkhash].js' }, resolve: { // treat source directory as root modules: [srcDir, 'node_modules'], extensions: ['.js', '.jsx', '.ts', '.tsx', '.css', 'less'], alias: { '~': srcDir, ...webpackCommonConfig.alias } }, node: { fs: 'empty', net: 'empty' }, devtool: 'source-map', performance: { hints: 'warning' }, module: { rules: [ { test: /\.jsx?$/, include: srcDir, use: [{ loader: 'eslint-loader', options: { emitWarning: false, // no warning in production formatter: require('eslint-friendly-formatter') } }], enforce: 'pre' }, { test: /\.jsx?$/, include: [ srcDir, // AE and ES modules need transform /@ae\.sdp\.nd[/\\](?!node_modules)/, /[/\\]node_modules.*[/\\]((lodash-)?es)[/\\](?!node_modules)/ ], use: 'babel-loader' }, { test: /\.tsx?$/, include: [ srcDir, /@ae\.sdp\.nd[/\\](?!node_modules)/ ], use: [{ loader: 'babel-loader' }, { loader: 'ts-loader', options: { transpileOnly: true } }] }, { test: /\.css$/, use: getCSSLoader('css', LANGS) }, { test: /\.less$/, use: getCSSLoader('less', LANGS) }, { test: /\.(png|jpg|gif|svg|woff2?|eot|ttf)(\?.*)?$/, use: [{ loader: 'url-loader', options: { limit: 8192, name: '[name].[ext]?[hash:7]' } }] } ] }, plugins: [ ...webpackCommonConfig.plugins, new webpack.DefinePlugin({ 'process.env.NODE_ENV': JSON.stringify('production'), 'process.env.SDP_ENV': JSON.stringify(SDP_ENV), 'process.env.LANGS': JSON.stringify(LANGS), 'process.env.I18N': JSON.stringify(i18nHashMap) }), new HtmlWebpackPlugin({ SDP_ENV: process.env.SDP_ENV, ORG_NAME, CDN: ae.cdn || {}, filename: 'index.html', template: tplPath, title: `${pkg.name} - ${pkg.description}`, hash: false, inject: !useCDN(pkg.cdn, process.env.SDP_ENV), minify: { collapseWhitespace: false, minifyJS: false } }), new CopyWebpackPlugin(copyPluginPatterns, { ignore: ['README.md'] }), new FaviconsWebpackPlugin({ logo: path.resolve(srcDir, 'assets/favicon.svg'), prefix: 'icons-[hash:7]/', icons: { android: false, appleIcon: false, appleStartup: false, coast: false, favicons: true, firefox: false, opengraph: false, twitter: false, yandex: false, windows: true } }), // 按需优化 moment // TODO: 根据配置的语言,而非默认中英文 new webpack.ContextReplacementPlugin(/moment[\\/]locale$/, /^\.\/(zh-cn|en-us)$/), new webpack.LoaderOptionsPlugin({ minimize: true, options: { context: workDir } }), new webpack.optimize.UglifyJsPlugin({ compress: { unused: true, dead_code: true, warnings: false }, sourceMap: true }), // Compress extracted CSS. We are using this plugin so that possible // duplicated CSS from different components can be deduped. new OptimizeCSSPlugin({ cssProcessorOptions: { safe: true } }), // extract css into its own file new ExtractTextPlugin({ filename: '[name].[contenthash].css', allChunks: true }) ] } export default webpackConfig