UNPKG

@wibetter/akfun

Version:

前端脚手架:支持Vue技术栈和react技术栈

158 lines (134 loc) 5.63 kB
const open = require('open'); const ora = require('ora'); const path = require('path'); const https = require('https'); const fs = require('fs'); const express = require('express'); const webpack = require('webpack'); const portfinder = require('portfinder'); const checkVersion = require('./check-versions'); const { createProxyMiddleware } = require('http-proxy-middleware'); const { resolve } = require('./utils/pathUtils'); // 引入当前项目配置文件 const projectConfig = require('./config/index'); const defaultConfig = require('./config/default.config'); const getDevWebpackConfig = require('./webpack/webpack.dev.conf'); const deepMergeConfig = require('./utils/deepMergeConfig'); const { curConsoleTag } = require('./utils/akfunParams'); // 构建脚本:一般用于构建开发环境的代码(包含热更新、接口代理等功能) module.exports = function (akfunConfig, _consoleTag) { const consoleTag = _consoleTag || curConsoleTag; let config = projectConfig; // 默认使用执行命令目录下的配置数据 if (akfunConfig) { // 参数中的config配置优先级最高 config = deepMergeConfig(defaultConfig, akfunConfig); } // 检查当前npm版本号是否匹配 checkVersion(); const spinner = ora(`${consoleTag}开启调试模式...`).start(); /** * 如果 Node 的环境无法判断当前是 dev / product 环境 * 使用 config.dev.NODE_ENV 作为当前的环境 */ if (!process.NODE_ENV) { process.NODE_ENV = config.dev.NODE_ENV; // 此时process.NODE_ENV = ‘development’; } // default port where dev server listens for incoming traffic // 如果没有指定运行端口,使用 config.dev.port 作为运行端口 const port = process.env.PORT || config.dev.port; // automatically open browser, if not set will be false // 是否自动打开浏览器 const autoOpenBrowser = !!config.dev.autoOpenBrowser; // 使用 express 启动一个服务 const app = express(); // 获取开发环境的webpack基本配置 const webpackConfig = getDevWebpackConfig(config); // serve pure public assets // 拼接 public 文件夹的静态资源路径 const staticPath = path.posix.join(config.dev.assetsPublicPath, config.dev.assetsSubDirectory); app.use(staticPath, express.static(resolve('public'))); const compiler = webpack(webpackConfig); // 启动 webpack 进行编译 // 启动 webpack-dev-middleware,将编译后的文件暂存到内存中 const devMiddleware = require('webpack-dev-middleware')(compiler, { publicPath: webpackConfig.output.publicPath, stats: true }); // serve webpack bundle output app.use(devMiddleware); // 启动 webpack-hot-middleware,也就是我们常说的 Hot-reload const hotMiddleware = require('webpack-hot-middleware')(compiler, { log: false, heartbeat: 2000 }); // enable hot-reload and state-preserving // compilation error display app.use(hotMiddleware); // Define HTTP proxies to your custom API backend // https://github.com/chimurai/http-proxy-middleware // 使用 config.dev.proxyTable 的配置作为 proxyTable 的代理配置 const proxyTable = config.dev.proxyTable; if (proxyTable && JSON.stringify(proxyTable) !== '{}') { // 将 proxyTable 中的请求配置挂在到启动的 express 服务上 // proxy api requests Object.keys(proxyTable).forEach((context) => { let options = proxyTable[context]; if (typeof options === 'string') { options = { target: options }; } app.use(context, createProxyMiddleware(options)); }); } // 使用 connect-history-api-fallback 匹配资源,如果不匹配就可以重定向到指定地址 // handle fallback for HTML5 history API app.use(require('connect-history-api-fallback')()); const afterCreateServerAction = (isHttps, port) => { spinner.succeed(`${consoleTag}调试模式已开启!`); process.env.PORT = port; const uri = isHttps ? `https://${config.dev.hostname}` : `http://${config.dev.hostname}:${port}`; console.log(`> Listening at ${uri}\n`); // 打印当前环境中的首个html和css地址 const projPath = `${uri}${webpackConfig.output.publicPath}`; let entryConfig = webpackConfig.entry || {}; // 获取构建入口配置 const entryFiles = (entryConfig && Object.keys(entryConfig)) || []; if (entryFiles.length > 0) { // 获取第一个入口文件 const filename = entryFiles[0]; console.info( `当前运行脚本:\n ${projPath}${filename}.js\n当前运行样式[可能不存在]:\n${projPath}${filename}.css` ); // 是否自动打开浏览器并跳转到第一个入口页面 if (!config.dev.closeHtmlWebpackPlugin && autoOpenBrowser) { open(`${projPath}${filename}.html`, { wait: true }); } } }; if (config.dev.https) { const sslOptions = { key: fs.readFileSync(path.resolve(__dirname, './ssl/localhost.key')), cert: fs.readFileSync(path.resolve(__dirname, './ssl/localhost.cert')), requestCert: false, rejectUnauthorized: false }; var httpsServer = https.createServer(sslOptions, app); devMiddleware.waitUntilValid(() => { httpsServer.listen(443, () => { afterCreateServerAction(true, port); }); }); } else { portfinder.basePort = port; devMiddleware.waitUntilValid(() => { portfinder.getPort((err, port) => { if (err) { _reject(err); } app.listen(port, () => { afterCreateServerAction(false, port); }); }); }); } };