import * as fs from 'fs-extra' ; import * as HtmlWebpackPlugin from 'html-webpack-plugin' ; import * as path from 'path' ; import * as prettier from 'prettier' ; import { pri , tempPath } from '../../../node' ; import * as pipe from '../../../node/pipe' ; import { analyseProject } from '../../../utils/analyse-project' ; import { createEntry } from '../../../utils/create-entry' ; import { exec } from '../../../utils/exec' ; import { globalState } from '../../../utils/global-state' ; import { logInfo , spinner } from '../../../utils/log' ; import { findNearestNodemodulesFile } from '../../../utils/npm-finder' ; import { plugin } from '../../../utils/plugins' ; import { assetsPath } from '../../../utils/structor-config' ; import { runWebpack } from '../../../utils/webpack' ; import { getStaticHtmlPaths } from './generate-static-html' ; import { IOpts } from './interface' ; import { tsPlusBabel } from '../../../utils/ts-plus-babel' ; export const buildProject = async ( opts = { } ) => { const result = await spinner ( 'Analyse project' , async ( ) => { const analyseInfo = await analyseProject ( ) ; const entryPath = await createEntry ( ) ; return { analyseInfo , entryPath , } ; } ) ; const staticHtmlPaths = getStaticHtmlPaths ( result . analyseInfo ) ; const stats = await runWebpack ( { mode : 'production' , entryPath : { [ path . basename ( pri . sourceConfig . outFileName , '.js' ) ] : result . entryPath , ... pri . sourceConfig . entries , } , outFileName : '[name].js' , publicPath : opts . publicPath , pipeConfig : async ( config ) => { if ( pri . sourceConfig . useHtmlTemplate ) { staticHtmlPaths . forEach ( staticHtmlPath => { config . plugins . push ( new HtmlWebpackPlugin ( { title : pri . sourceConfig . title || globalState . projectRootPath . split ( path . sep ) . pop ( ) , filename : staticHtmlPath , template : path . join ( __dirname , '../../../../template-project.ejs' ) , } ) ) ; } ) ; } return config ; } , } ) ; const tempSwPath = path . join ( pri . projectRootPath , tempPath . dir , 'static/sw.js' ) ; const targetSwPath = path . join ( globalState . projectRootPath , pri . sourceConfig . distDir , 'sw.js' ) ; if ( fs . existsSync ( tempSwPath ) ) { const tempSwContent = fs . readFileSync ( tempSwPath ) . toString ( ) ; const targetSwContent = await pipe . get ( 'serviceWorkerAfterProdBuild' , tempSwContent ) ; fs . outputFileSync ( targetSwPath , prettier . format ( targetSwContent , { semi : true , singleQuote : true , parser : 'babylon' , } ) ) ; } await copyAssets ( ) ; plugin . buildAfterProdBuild . forEach ( afterProdBuild => { return afterProdBuild ( stats ) ; } ) ; } ; export const buildComponent = async ( ) => { await spinner ( `build source files` , async ( ) => { await tsPlusBabel ( false ) ; } ) ; } ; export const buildPlugin = async ( ) => { await buildComponent ( ) ; } ; async function copyAssets ( ) { const sourceAssetsPath = path . join ( pri . sourceRoot , assetsPath . dir ) ; if ( ! fs . existsSync ( sourceAssetsPath ) ) { return ; } const distAssetsPath = path . join ( pri . projectRootPath , pri . sourceConfig . distDir , assetsPath . dir ) ; if ( fs . existsSync ( distAssetsPath ) ) { logInfo ( 'assets path exists in distDir, so skip /assets copy.' ) ; } else { await fs . copy ( sourceAssetsPath , distAssetsPath ) ; } } export async function prepareBuild ( opts = { } ) { await spinner ( 'Clean project.' , async ( ) => { await exec ( `${ findNearestNodemodulesFile ( '.bin/rimraf' ) } ${ pri . projectRootPath }/${ tempPath . dir }` ) ; await pri . project . ensureProjectFiles ( ) ; if ( ! opts . skipLint ) { await pri . project . lint ( { lintAll : true , needFix : false , showBreakError : true , } ) ; } await pri . project . checkProjectFiles ( ) ; } ) ; }