当前位置: 首页 > news >正文

保定市网站建设_网站建设公司_后端开发_seo优化

专业的营销型网站定制,wordpress mysql5.7,微信小程序万能开挂器,北京市建设集团有限公司戳蓝字前端优选关注我们哦#xff01;一.什么是Vite#xff1f;法语Vite(轻量#xff0c;轻快)vite 是一个基于 Vue3单文件组件的非打包开发服务器#xff0c;它做到了本地快速开发启动、实现按需编译、不再等待整个应用编译完成的功能作用。对于Vite的描述前端优选关注我们哦一.什么是Vite法语Vite(轻量轻快)vite 是一个基于 Vue3单文件组件的非打包开发服务器它做到了本地快速开发启动、实现按需编译、不再等待整个应用编译完成的功能作用。对于Vite的描述针对Vue单页面组件的无打包开发服务器可以直接在浏览器运行请求的vue文件。面向现代浏览器Vite基于原生模块系统 ESModule 实现了按需编译而在webpack的开发环境却很慢是因为其开发时需要将进行的编译放到内存中打包所有文件。Vite有如此多的优点那么它是如何实现的呢二.Vite的实现原理我们先来总结下Vite的实现原理Vite在浏览器端使用的是 export import 方式导入和导出的模块vite同时实现了按需加载Vite高度依赖module script特性。实现过程如下:在 koa 中间件中获取请求 body通过 es-module-lexer 解析资源 ast 并拿到 import 内容判断 import 的资源是否是 npm 模块返回处理后的资源路径vue /modules/vue将要处理的template,script,style等所需依赖以http请求的形式、通过query参数的形式区分并加载SFC(vue单文件)文件各个模块内容。接下来将自己手写一个Vite来实现相同的功能三.手把手实现Vite1.安装依赖实现Vite的环境需要es-module-lexer、koa、koa-static、magic-string模块搭建npm install es-module-lexer koa koa-static magic-string这些模块的功能是koa、koa-static 是vite内部使用的服务框架es-module-lexer 用于分析ES6import语法magic-string 用来实现重写字符串内容。2.基本结构搭建Vite需要搭建一个koa服务const Koa  require(koa);function createServer() {    const app  new Koa();    const root  process.cwd();    // 构建上下文对象    const context  {        app,        root    }    app.use((ctx, next)  {        // 扩展ctx属性        Object.assign(ctx, context);        return next();    });    const resolvedPlugins  [    ];    // 依次注册所有插件    resolvedPlugins.forEach(plugin  plugin(context));    return app;}createServer().listen(4000);3.Koa静态服务配置用于处理项目中的静态资源const {serveStaticPlugin}  require(./serverPluginServeStatic);const resolvedPlugins  [ serveStaticPlugin];const path  require(path);function serveStaticPlugin({app,root}){    // 以当前根目录作为静态目录    app.use(require(koa-static)(root));    // 以public目录作为根目录    app.use(require(koa-static)(path.join(root,public)))}exports.serveStaticPlugin  serveStaticPlugin;目的是让当前目录下的文件和public目录下的文件可以直接被访问4.重写模块路径const {moduleRewritePlugin}  require(./serverPluginModuleRewrite);const resolvedPlugins  [    moduleRewritePlugin,    serveStaticPlugin];const { readBody }  require(./utils);const { parse }  require(es-module-lexer);const MagicString  require(magic-string);function rewriteImports(source) {    let imports  parse(source)[0];    const magicString  new MagicString(source);    if (imports.length) {        for (let i  0; i             const { s, e }  imports[i];            let id  source.substring(s, e);            if (/^[^\/\.]/.test(id)) {                id  /modules/${id};                // 修改路径增加 /modules 前缀                magicString.overwrite(s, e, id);            }        }    }    return magicString.toString();}function moduleRewritePlugin({ app, root }) {    app.use(async (ctx, next)  {        await next();        // 对类型是js的文件进行拦截        if (ctx.body  ctx.response.is(js)) {            // 读取文件中的内容            const content  await readBody(ctx.body);            // 重写import中无法识别的路径            const r  rewriteImports(content);            ctx.body  r;        }    });}exports.moduleRewritePlugin  moduleRewritePlugin;对js文件中的 import 语法进行路径的重写改写后的路径会再次向服务器拦截请求读取文件内容const { Readable }  require(stream)async function readBody(stream) {    if (stream instanceof Readable) { //         return new Promise((resolve, reject)  {            let res  ;            stream                .on(data, (chunk)  res  chunk)                .on(end, ()  resolve(res));        })    }else{        return stream.toString()    }}exports.readBody  readBody5.解析 /modules 文件const {moduleResolvePlugin}  require(./serverPluginModuleResolve);const resolvedPlugins  [    moduleRewritePlugin,    moduleResolvePlugin,    serveStaticPlugin];const fs  require(fs).promises;const path  require(path);const { resolve }  require(path);const moduleRE  /^\/modules\//; const {resolveVue}  require(./utils)function moduleResolvePlugin({ app, root }) {    const vueResolved  resolveVue(root)    app.use(async (ctx, next)  {        // 对 /modules 开头的路径进行映射        if(!moduleRE.test(ctx.path)){             return next();        }        // 去掉 /modules/路径        const id  ctx.path.replace(moduleRE,);        ctx.type  js;        const content  await fs.readFile(vueResolved[id],utf8);        ctx.body  content    });}exports.moduleResolvePlugin  moduleResolvePlugin;将/modules 开头的路径解析成对应的真实文件并返回给浏览器const path  require(path);function resolveVue(root) {    const compilerPkgPath  path.resolve(root, node_modules, vue/compiler-sfc/package.json);    const compilerPkg  require(compilerPkgPath);    // 编译模块的路径  node中编译    const compilerPath  path.join(path.dirname(compilerPkgPath), compilerPkg.main);    const resolvePath  (name)  path.resolve(root, node_modules, vue/${name}/dist/${name}.esm-bundler.js);    // dom运行    const runtimeDomPath  resolvePath(runtime-dom)    // 核心运行    const runtimeCorePath  resolvePath(runtime-core)    // 响应式模块    const reactivityPath  resolvePath(reactivity)    // 共享模块    const sharedPath  resolvePath(shared)    return {        vue: runtimeDomPath,        vue/runtime-dom: runtimeDomPath,        vue/runtime-core: runtimeCorePath,        vue/reactivity: reactivityPath,        vue/shared: sharedPath,        compiler: compilerPath,    }}编译的模块使用commonjs规范,其他文件均使用es6模块6.处理process的问题浏览器中并没有process变量所以我们需要在html中注入process变量const {htmlRewritePlugin}  require(./serverPluginHtml);const resolvedPlugins  [    htmlRewritePlugin,    moduleRewritePlugin,    moduleResolvePlugin,    serveStaticPlugin];const { readBody }  require(./utils);function htmlRewritePlugin({root,app}){    const devInjection          app.use(async(ctx,next){        await next();        if(ctx.response.is(html)){            const html  await readBody(ctx.body);            ctx.body  html.replace(//,$${devInjection})        }    })}exports.htmlRewritePlugin  htmlRewritePlugin在html的head标签中注入脚本7.处理.vue后缀文件const {vuePlugin}  require(./serverPluginVue)const resolvedPlugins  [    htmlRewritePlugin,    moduleRewritePlugin,    moduleResolvePlugin,    vuePlugin,    serveStaticPlugin];const path  require(path);const fs  require(fs).promises;const { resolveVue }  require(./utils);const defaultExportRE  /((?:^|\n|;)\s*)export default/function vuePlugin({ app, root }) {    app.use(async (ctx, next)  {        if (!ctx.path.endsWith(.vue)) {            return next();        }        // vue文件处理        const filePath  path.join(root, ctx.path);        const content  await fs.readFile(filePath, utf8);        // 获取文件内容        let { parse, compileTemplate }  require(resolveVue(root).compiler);        let { descriptor }  parse(content); // 解析文件内容        if (!ctx.query.type) {            let code  ;            if (descriptor.script) {                let content  descriptor.script.content;                let replaced  content.replace(defaultExportRE, $1const __script );                code  replaced;            }            if (descriptor.template) {                const templateRequest  ctx.path  ?typetemplate                code  \nimport { render as __render } from ${JSON.stringify(                    templateRequest                )};                code  \n__script.render  __render            }            ctx.type  js            code  \nexport default __script;            ctx.body  code;        }        if (ctx.query.type  template) {            ctx.type  js;            let content  descriptor.template.content;            const { code }  compileTemplate({ source: content });            ctx.body  code;        }    })}exports.vuePlugin  vuePlugin;在后端将.vue文件进行解析成如下结果import {reactive} from /modules/vue;const __script  {  setup() {    let state  reactive({count:0});    function click(){      state.count 1    }    return {      state,      click    }  }}import { render as __render } from /src/App.vue?typetemplate__script.render  __renderexport default __scriptimport { toDisplayString as _toDisplayString, createVNode as _createVNode, Fragment as _Fragment, openBlock as _openBlock, createBlock as _createBlock } from /modules/vueexport function render(_ctx, _cache) {  return (_openBlock(), _createBlock(_Fragment, null, [    _createVNode(div, null, 计数器:  _toDisplayString(_ctx.state.count), 1 /* TEXT */),    _createVNode(button, {      onClick: _cache[1] || (_cache[1]  $event  (_ctx.click($event)))    }, )  ], 64 /* STABLE_FRAGMENT */))}解析后的结果可以直接在createApp方法中进行使用8.小结到这里基本的一个Vite就实现了。总结一下就是通过Koa服务实现了按需读取文件省掉了打包步骤以此来提升项目启动速度这中间包含了一系列的处理诸如解析代码内容、静态文件读取、浏览器新特性实践等等。其实Vite的内容远不止于此这里我们实现了非打包开发服务器那它是如何做到热更新的呢下次将手把手实现Vite热更新原理~历史好文推荐1、Vue3之——和Vite不得不说的事                        2、大厂面试算法之斐波那契数列                        3、2020字节跳动面试题一面解析                          点个在看大家都看
http://www.ihoyoo.com/news/134282.html

相关文章:

  • 宁波做外贸网站建设微信公众号做推送的网站
  • 牛商网网站建设多少钱手机制作表格的软件免费
  • 专业建站商品详情页设计模板
  • 哪个公司做网站好网站提示危险怎么办
  • 网站开发的形式有( )做网站的论文摘要
  • 特殊教育学校网站建设方案荆门做网站公众号的公司
  • 腾讯静态网站托管建设棋牌网站流程
  • 网站建设费分多少期摊销企业网站制作是什么
  • 免费发链接的网站网络公司给我做网站我有没有源代码版权吗?
  • 外贸网站虚拟主机怎么做垂直自营网站
  • 做网站需要网页嵌套吗建一个电商平台多少钱
  • 做推广类门户网站怎么样长白山网站学做管理平台
  • 社区网站开发需求文档为什么做网站ppt
  • 网站开发工程师有证书考试吗带flash的网站
  • 高端定制网站开发设计建站流程网络优化培训
  • 素材网站官网科技设计网站有哪些
  • 浦口区建设网站建外贸网站公司
  • 东莞企业怎么做网站建设鹤岗哈尔滨网站建设
  • 国内免费的短视频素材网站站长友情链接平台
  • 百度公司网站seo方案中山网站建设的企业
  • 卖线面网站广州番禺房价最新楼盘价格
  • 网站建设策划书论文公司注销 网站备案申请表
  • 网站制作多少钱一个网页无法访问未连接上服务器
  • 网站app免费生成软件网站怎么做图片
  • 钟表商城网站建设方案自助在线设计平台
  • 安徽住房和城乡建设部网站官网网站里怎么做301指向
  • 建网站与建网页的区别做网站有多砸钱
  • seo网站营销公司哪家好医院网站做竞价需要注意广告法
  • 网站开发用c 语言小程序开发平台好的有哪些
  • 西安建设主管部门官方网站盐城建设局网站