diff --git a/lib/dev.js b/lib/dev.js index a3d67ca..4854dfb 100644 --- a/lib/dev.js +++ b/lib/dev.js @@ -3,6 +3,7 @@ import https from 'https' import fs from 'iofs' import { join, resolve, dirname } from 'path' import { parse } from 'url' +import socket from './ws.js' import { compileScss, parseJs, compileVue, parseHtml } from './compile-vue.js' @@ -12,12 +13,15 @@ import { COMMON_HEADERS } from './constants.js' const noc = Buffer.from('') const SERVER_OPTIONS = {} -export default function createServer(root = '', conf = {}) { +export default async function createServer(root = '', conf = {}) { const IS_MPA = Object.keys(conf.pages).length > 1 const PORT = conf.devServer.port || 8080 const USE_HTTPS = conf.devServer.https const DOMAIN = conf.devServer.domain || 'localhost' - const WEB_SERVER = USE_HTTPS ? https : http + const server = (USE_HTTPS ? https : http) + .createServer(SERVER_OPTIONS) + .listen(PORT) + let indexPage = Object.keys(conf.pages) .map(it => { let tmp = it + '.html' @@ -37,29 +41,41 @@ export default function createServer(root = '', conf = {}) { } } - WEB_SERVER.createServer(SERVER_OPTIONS, function (req, res) { - let pathname = parse(req.url.slice(1)).pathname - let pageName = '', - isIndex = false // 是否渲染目录页 - let ext + server + .on('request', function (req, res) { + let pathname = parse(req.url.slice(1)).pathname + let pageName = '', + isIndex = false // 是否渲染目录页 + let ext - if (pathname) { - pathname = pathname.split('/') + if (pathname) { + pathname = pathname.split('/') - if (pathname[0].endsWith('.html')) { - pageName = pathname.shift() + if (pathname[0].endsWith('.html')) { + pageName = pathname.shift() - let tmp = pageName.split('.') + let tmp = pageName.split('.') - ext = tmp.pop() - pageName = tmp.join('.') + ext = tmp.pop() + pageName = tmp.join('.') - currentPage = pageName - pagesDir = dirname(conf.pages[pageName].entry) + currentPage = pageName + pagesDir = dirname(conf.pages[pageName].entry) + } else { + if (currentPage) { + ext = pathname.at(-1).split('.').pop() + pageName = currentPage + } else { + pageName = Object.keys(conf.pages).pop() + currentPage = pageName + pagesDir = dirname(conf.pages[pageName].entry) + ext = 'html' + } + } + pathname = pathname.join('/') } else { - if (currentPage) { - ext = pathname.at(-1).split('.').pop() - pageName = currentPage + if (IS_MPA) { + isIndex = true } else { pageName = Object.keys(conf.pages).pop() currentPage = pageName @@ -67,135 +83,124 @@ export default function createServer(root = '', conf = {}) { ext = 'html' } } - pathname = pathname.join('/') - } else { - if (IS_MPA) { - isIndex = true - } else { - pageName = Object.keys(conf.pages).pop() - currentPage = pageName - pagesDir = dirname(conf.pages[pageName].entry) + // 修正history路由时的访问 + if (pathname === ext) { ext = 'html' } - } - // 修正history路由时的访问 - if (pathname === ext) { - ext = 'html' - } - for (let k in COMMON_HEADERS) { - res.setHeader(k, COMMON_HEADERS[k]) - } - - if (isIndex) { - res.setHeader('content-type', MIME_TYPES.html) - res.writeHead(200, 'OK') - res.end('') - } else { - res.setHeader('accept-ranges', 'bytes') - - let code = '' - - switch (ext) { - case 'html': - { - res.setHeader('content-type', MIME_TYPES.html) - - let page = conf.pages[pageName] - let entry = fs.cat(page.entry).toString() - let html = fs.cat(join(process.cwd(), 'index.html')).toString() - - entry = parseJs(entry, conf.imports, { IS_MPA, currentPage }) - - code = parseHtml(html, { page, imports: conf.imports, entry }) - } - - break - - case 'vue': - { - let rpath = pathname.replace(/^assets\/js\//, '') - let file - - if (IS_MPA) { - file = join(pagesDir, rpath) - } else { - file = join(root, rpath) - } - if (!fs.isfile(file)) { - file = file.replace(/\.vue$/, '/index.vue') - } - - // console.log('>>>>', file) - code = compileVue(file, conf.imports, { - IS_MPA, - currentPage, - root, - pagesDir - }) - res.setHeader('content-type', MIME_TYPES.js) - } - break - - case 'scss': - case 'css': - { - let file = join(root, pathname.replace(/^assets\/css\//, '')) - code = compileScss(file) - res.setHeader('content-type', MIME_TYPES.css) - } - break - - case 'js': - { - pathname = pathname.replace(/^assets\/js\//, '') - let file - if (pathname.startsWith(currentPage)) { - file = join(pagesDir, pathname) - } else { - file = join(root, pathname) - } - if (fs.isfile(file)) { - code = fs.cat(file) - } else { - file = file.replace(/\.js$/, '/index.js') - code = fs.cat(file) - } - code = parseJs(code + '', conf.imports, { IS_MPA, currentPage }) - res.setHeader('content-type', MIME_TYPES.js) - } - - break - - case 'png': - case 'jpg': - case 'jpeg': - case 'webp': - case 'gif': - case 'svg': - case 'ico': - case 'bmp': - res.setHeader('content-type', MIME_TYPES[ext]) - code = fs.cat(join(root, pathname)) - if (code === null) { - console.error(pathname, '文件不存在') - res.writeHead(404, 'Not Found') - res.end('') - return - } - break - - default: - res.setHeader('content-type', MIME_TYPES[ext] || MIME_TYPES.html) - break + for (let k in COMMON_HEADERS) { + res.setHeader(k, COMMON_HEADERS[k]) } - res.setHeader('content-length', Buffer.byteLength(code || noc)) - res.writeHead(200, 'OK') - res.end(code || noc) - } - }) - .listen(PORT) + if (isIndex) { + res.setHeader('content-type', MIME_TYPES.html) + res.writeHead(200, 'OK') + res.end('') + } else { + res.setHeader('accept-ranges', 'bytes') + + let code = '' + + switch (ext) { + case 'html': + { + res.setHeader('content-type', MIME_TYPES.html) + + let page = conf.pages[pageName] + let entry = fs.cat(page.entry).toString() + let html = fs.cat(join(process.cwd(), 'index.html')).toString() + + entry = parseJs(entry, conf.imports, { IS_MPA, currentPage }) + + code = parseHtml(html, { page, imports: conf.imports, entry }) + } + + break + + case 'vue': + { + let rpath = pathname.replace(/^assets\/js\//, '') + let file + + if (IS_MPA) { + file = join(pagesDir, rpath) + } else { + file = join(root, rpath) + } + if (!fs.isfile(file)) { + file = file.replace(/\.vue$/, '/index.vue') + } + + // console.log('>>>>', file) + code = compileVue(file, conf.imports, { + IS_MPA, + currentPage, + root, + pagesDir + }) + res.setHeader('content-type', MIME_TYPES.js) + } + break + + case 'scss': + case 'css': + { + let file = join(root, pathname.replace(/^assets\/css\//, '')) + code = compileScss(file) + res.setHeader('content-type', MIME_TYPES.css) + } + break + + case 'js': + { + pathname = pathname.replace(/^assets\/js\//, '') + let file + if (pathname.startsWith(currentPage)) { + file = join(pagesDir, pathname) + } else { + file = join(root, pathname) + } + if (fs.isfile(file)) { + code = fs.cat(file) + } else { + file = file.replace(/\.js$/, '/index.js') + code = fs.cat(file) + } + code = parseJs(code + '', conf.imports, { IS_MPA, currentPage }) + res.setHeader('content-type', MIME_TYPES.js) + } + + break + + case 'png': + case 'jpg': + case 'jpeg': + case 'webp': + case 'gif': + case 'svg': + case 'ico': + case 'bmp': + res.setHeader('content-type', MIME_TYPES[ext]) + code = fs.cat(join(root, pathname)) + if (code === null) { + console.error(pathname, '文件不存在') + res.writeHead(404, 'Not Found') + res.end('') + return + } + break + + default: + res.setHeader('content-type', MIME_TYPES[ext] || MIME_TYPES.html) + break + } + + res.setHeader('content-length', Buffer.byteLength(code || noc)) + res.writeHead(200, 'OK') + res.end(code || noc) + } + }) + .on('error', err => { console.log(`${PORT}端口被占用~~~`) conf.devServer.port = PORT + 1 @@ -216,4 +221,10 @@ export default function createServer(root = '', conf = {}) { PORT ) }) + + const ws = await socket(server) + + console.log(ws) + + ws.send('hello from vue-live') } diff --git a/lib/ws.js b/lib/ws.js new file mode 100644 index 0000000..0f4826e --- /dev/null +++ b/lib/ws.js @@ -0,0 +1,25 @@ +/** + * {} + * @author yutent + * @date 2023/01/17 17:32:51 + */ +import { WebSocketServer } from 'ws' + +function defer() { + var o = {} + o.promise = new Promise((resolve, reject) => { + o.resolve = resolve + o.reject = reject + }) + return o +} + +export default function (server) { + var _ = defer() + var conn = new WebSocketServer({ server, path: '/ws-vue-live' }) + + conn.on('connection', client => { + _.resolve(client) + }) + return _.promise +} diff --git a/package.json b/package.json index c7ad3ae..5dabffc 100644 --- a/package.json +++ b/package.json @@ -9,6 +9,7 @@ "@bytedo/sass": "^1.54.8", "chokidar": "^3.5.3", "esbuild": "^0.15.13", - "iofs": "^1.5.2" + "iofs": "^1.5.2", + "ws": "^8.12.0" } }