TypeScript

TypeScript

TypeScript is an open-source programming language developed and maintained by Microsoft. It is a strict syntactical superset of JavaScript, and adds optional static typing to the language. TypeScript is designed for development of large applications and transcompiles to JavaScript.
Noemi  Hintz

Noemi Hintz

1656759600

A Plugin for Vite That Convert From Require Syntax to Import

vite-plugin-require-transform

 A vite plugin that converts the code from require syntax to import

Why vite-plugin-require-transform

"require syntax" is supported when develop with Webpack cause it transformed it internally.

but when serve with Vite error "require is not defined" will show up.

This plugin amis to support require when serve with vite.

Install

yarn add -D vite-plugin-require-transform

or

npm i vite-plugin-require-transform --save-dev

Usage

// vite.config.(t|j)s

import { defineConfig } from 'vite';

/**
 * @param match
 * Regular expression in string or Regexp type,
 *  or a match predicate  (this: vite transform context, code: string, id: file name string) => void
 * @returns transformed code
 */
import requireTransform from 'vite-plugin-require-transform';

export default defineConfig({
  plugins: [
    // passing string type Regular expression
    requireTransform({}),
  ],
});


// check the vite-plugin-require-transform params'type 
export type VitePluginRequireTransformParamsType = {
    //filter files that should enter the plugin
    fileRegex?: RegExp = /.ts$|.tsx$/ ,
    //prefix that would plugin into the requireSpecifier 
    importPrefix? = '_vite_plugin_require_transform_': string,
    //to deal with the requireSpecifier
    importPathHandler?: Function
}

What vite-plugin-require-transform actually do

you can also check the test directory to see the cases.

case 1:

const case1 = require("case1");
console.log("case1", case1)

will be transformed into

import _vite_plugin_require_transform_case1 from "case1";
const case1 = _vite_plugin_require_transform_case1;
console.log("case1", case1);

case 2:

example A

const case2A = location.host == 'test' ? null : require("case2");

if(location.host == 'test1' ){
    case2A.start();
}

case2A.stop();

will be transformed into

import { start as _vite_plugin_require_transform_case2start, stop as _vite_plugin_require_transform_case2stop } from "case2";
const _vite_plugin_require_transform_case2 = {
  start: _vite_plugin_require_transform_case2start,
  stop: _vite_plugin_require_transform_case2stop
};
const case2A = location.host == 'test' ? null : _vite_plugin_require_transform_case2;

if (location.host == 'test1') {
  case2A.start();
}

case2A.stop();

example B

const case2B = {
    test:require('test2B').Something
}

will be transformed into

import { Something as _vite_plugin_require_transform_test2BSomething } from "test2B";
const case2B = {
  test: _vite_plugin_require_transform_test2BSomething
};

example C

const case2c =require('test2C')


case2c.forEach((item)=>{
    console.log('item',item)
})

will be transformed into

import _vite_plugin_require_transform_test2C from "test2C";
const case2c = _vite_plugin_require_transform_test2C;
case2c.forEach(item => {
  console.log('item', item);
});

case 3:

when exist a case as same fileName,different extensions,by default it would be error cause the plugin only capture the path without extension.


//same path,different extension
const testCaseA = require("caseA.extA?aaa");
const testCaseB = require("caseA.extB?bbb");

console.log("caseA", testCaseA)
console.log("caseB", testCaseB)

so we need to make a importPathHandler to deal with the situtation

//check out __test__/index
glob("__test__/case3/*.ts", {
    ignore: "**/*transformed_result.ts"
}, async (err, files) => {
    for (const file of files) {
        const fileContent = readFileSync(file, 'utf-8');
        const transformedContent = await vitePluginRequireTransform(
            {
                importPathHandler: (requirePath: string) => {
                    return requirePath.replace('.', '_').replace('?', "_");
                }
            }
        ).transform(fileContent, file);
        writeFileSync(file.replace('.ts', '_transformed_result.ts'), transformedContent.code);
    }
})  

will be transformed into

import _vite_plugin_require_transform_caseA_extB_bbb from "caseA.extB?bbb";
import _vite_plugin_require_transform_caseA_extA_aaa from "caseA.extA?aaa";
//same path,different extension
const testCaseA = _vite_plugin_require_transform_caseA_extA_aaa;
const testCaseB = _vite_plugin_require_transform_caseA_extB_bbb;
console.log("caseA", testCaseA);
console.log("caseB", testCaseB);

Author: WarrenJones
Source code: https://github.com/WarrenJones/vite-plugin-require-transform
License:

#vite #typescript 

A Plugin for Vite That Convert From Require Syntax to Import
Michele  Herman

Michele Herman

1656759600

Vite Plugin inspect: Inspect The Intermediate State Of Vite Plugins.

vite-plugin-inspect

Inspect the intermediate state of Vite plugins. Useful for debugging and authoring plugins.

Install

npm i -D vite-plugin-inspect

Since vite-plugin-inspect@v0.5.0, Vite v2.9 or above is required.

Add plugin to your vite.config.ts:

// vite.config.ts
import Inspect from 'vite-plugin-inspect'

export default {
  plugins: [
    Inspect(), // only applies in dev mode
  ],
}

Then visit localhost:3000/__inspect/ to inspect the modules.


Author: antfu
Source code: https://github.com/antfu/vite-plugin-inspect
License:  MIT license

#vite #vue #typescript

Vite Plugin inspect: Inspect The Intermediate State Of Vite Plugins.
Meggie  Flatley

Meggie Flatley

1656752400

Vuelix: Vue 3 + Vite Template/framework

Vuelix

Vuelix is a Vue 3 + Vite starter template to scaffold new projects really fast and with a great developer experience.

Table of contents

Setup

Install Dependencies

npm install

Generate API client

npm run gen-api

NOTE: This command requires a java jvm to be installed, if you want to avoid asking all developers to install it check OpenAPI Client Generator for more info.

Start the development server

npm run dev

Build

To build the app, run

npm run build

And to preview it, after building the app run

npm run serve

Features

🚀 Vue 3 + Vite 2

The version 3 of Vue with its powerful Composition API is available in this project.

The new <script setup> SFCs syntax is also available and recommended.

Vite is the lightning Fast Next Generation Frontend Tooling that highly improves the development experience along with all the community-created plugins.

NOTE: The initial state of this project was generated using Vite oficial scaffolding: npm init vite@latest

See:

🦾 TypeScript and SCSS

TypeScript and SCSS languages are supported and strongly recommended.

See:

🗂 File system routing

Routes for vue-router will be auto-generated from Vue files in the src/pages using the file structure.

See:

📑 Layouts system

Vue components in the src/layouts dir are used as layouts. By default, default.vue will be used unless an alternative is specified in the route meta.

You can specify the layout in the page's SFCs like this:

<route lang="yaml">
meta:
  layout: home
</route>

See:

🔗 Path Aliasing

@/ is aliased to the ./src/ folder.

For example, instead of having

import HelloWorld from '../../../components/HelloWorld.vue'

you can use

import HelloWorld from '@/components/HelloWorld.vue'

😃 Universal Icons Framework

Use icons from any icon set, one syntax for all icons: Material Design Icons, Bootstrap Icons, Font Awesome, etc. All icons libraries are available powered by iconify and unplugin-icons. And don't worry, only the icons you use would be included in the final bundle, keeping the production build lightweight.

The usage is simple, if you want for instance a Material Design Icon (mdi) with name "thumb-up", then just place this inside your template:

<i-mdi-thumb-up />

Just by placing it, the unplugin-icons/resolver would look for the corresponding icon and in case the related iconify icon set is not installed, it would automatically install it using npm, e.g. @iconify-json/mdi.

The convention to use icons is as follows:

{prefix}-{collection}-{icon}

Where the prefix is "i", the collection is the collection ID from https://icon-sets.iconify.design/, and finally the icon is the icon name.

See:

✨ Routes Transitions

Route changes are animated. By default, the fade transition will be used unless an alternative is specified in the route meta.

The fade and slide-fade transitions are available. You can specify the transition in the page's SFCs like this:

<route lang="yaml">
meta:
  transition: slide-fade
</route>

NOTE: Transitions are not triggered between routes of the same type, therefore changing the parameters of the active route won't cause a route transition. This could be changed by using the route.fullPath instead of route.name as the key in RouterViewTransition.vue. More info: https://stackoverflow.com/a/70042452/4873750.

Route transitions can be deactivated by changing the provided enable-route-transitions value in main.ts.

See:

🪄 Eslint + Prettier

This project comes with the recommended Eslint configuration for Vue 3 plus integration with Prettier. Prettier helps formatting code while Eslint helps catching bugs in development.

When opening the project in VSCode, it will ask the developers to install Eslint and Prettier, because that way the VSCode settings.json will work and therefore both Prettier and Eslint fix will be executed when saving a file.

Aditionally, commands to lint, check and autoformat code are available in the scripts of package.json

See:

🔧 OpenAPI Client Generator

Manually creating an API client is hard to maintain and time demanding, but thanks to OpenAPI and its generators we can now generate the entire API client from an OpenAPI Spec.

To do so just place your spec in spec/schema.yml, then run:

npm run gen-api

Which would generate the API client in Typescript and place the generated code in src/api-client.

NOTE: This command requires java to be installed, because the OpenAPI generator is built with it, if you want to avoid asking all developers to install a jvm and run this command by themselves, just run it once you change the OpenAPI spec, and commit the generated code, for that you need to remove the /src/api-client line from the .gitignore. The reason we exclude the generated client by default if because it can always be generated from the spec (spec/schema.yml), and because the spec file is actually versioned, then the code reviewing is improved by checking only spec changes and not the generated code that nobody wrotes.

INFO: If you have a Mac with an M1 Chip, this page have the correct OpenJDK installers for you: https://www.azul.com/downloads/?os=macos&architecture=arm-64-bit

To use the generated APIs just initialize them and make it available for the rest of the application. The following is an example using Swagger Demo PetStore API:

// "api/index.ts"
import { PetApi } from '@/api-client'
export const petApi = new PetApi()

You can also configure the APIs parameters like basePath and provide your own axios instance with interceptors configured like this:

// "api/index.ts"
import { PetApi } from '@/api-client'
import { Configuration } from '@/api-client/configuration'
import axiosInstance from './axios'

// See Vite env vars: https://vitejs.dev/guide/env-and-mode.html
const config = new Configuration({ basePath: import.meta.env.BASE_URL })
export const petApi = new PetApi(config, undefined, axiosInstance)

Then in your Vue Components:

<!-- "pages/home.vue" -->
<script setup lang="ts">
  import { petApi } from '@/api'
  import { Pet, PetStatusEnum } from '@/api-client'
  import { ref } from 'vue'

  const pets = ref<Pet[]>()
  const loading = ref(false)

  async function testOpenAPI() {
    loading.value = true
    const { data } = await petApi.findPetsByStatus({ status: [PetStatusEnum.Available] })
    pets.value = data.slice(0, 10)
    loading.value = false
  }
</script>

See:

👤 Authentication System

The auth system consist on three main parts:

  • The Plugin
  • The Navigation Guards
  • The Axios Interceptors

The Auth Plugin

The plugin is installed in Vue's globalProperties with the name $auth, it includes an isAuthenticated property, an user object, an accessToken plus the login and logout functions. It can be used in templates like this:

<span v-if="$auth.isAuthenticated">
  Authenticated as <b>{{ $auth.user.email }}</b>
  <button @click="$auth.logout">Logout</button>
</span>
<span v-else>Not Authenticated</span>

The auth instance is created using the composition API, therefore we can alternatively retrieve it outside of components with the useAuth function:

import { useAuth } from './useAuth'

const auth = useAuth()
if (auth.isAuthenticated) {
  console.log(auth.userFullName)
}
<script setup lang="ts">
  import { useAuth } from './useAuth'
  import { watchEffect } from 'vue'

  const auth = useAuth()
  watchEffect(() => {
    console.log(auth.isAuthenticated)
  })
</script>

Aditionally, the auth plugin can be inspected in the Vue's Devtools panel when having the extension in the browser. The plugin's values are displayed when inspecting any component.

The Navigation Guards

The navigation guards protects pages from non-authenticated users and redirect them to the login page, by default all pages but the login page are protected.

In order to make a page available for non-authenticated users, a route meta boolean called public needs to be configured in the page. E.g:

<!-- pages/index.html -->
<route lang="yaml">
meta:
  public: true
</route>

The navigation guards can be disabled by changing the autoConfigureNavigationGuards when configuring the auth system:

// main.ts
import { createApp } from 'vue'
import { createAuth } from './auth'
import App from './App.vue'
import router from './router'

const auth = createAuth({
  router,
  loginRouteName: 'login',
  autoConfigureNavigationGuards: false,
})

const app = createApp(App)
app.use(router)
app.use(auth)

The Axios Interceptors

The axios interceptors helps appending auth information to requests and responses of APIs.

The main interceptor adds the Authorization header with a value of Bearer the-token-value to all authenticated requests.

This can be configured and disabled in the createAuth options:

// api/axios.ts
import axios from 'axios'

const axiosInstance = axios.create()
export default axiosInstance
// main.ts
import { createApp } from 'vue'
import { createAuth } from './auth'
import App from './App.vue'
import router from './router'
import axiosInstance from './api/axios'

const auth = createAuth({
  router,
  axios: {
    instance: axiosInstance,
    autoAddAuthorizationHeader: true, // default: false
    authorizationHeaderPrefix: 'Token', // default: 'Bearer'
  },
})

const app = createApp(App)
app.use(router)
app.use(auth)

See:

🌐 Internationalization: vue-i18n and vue-i18n-extract

The vue-i18n package is used as the internationalization system.

All translation files located in the locales dir are loaded automatically with the corresponding language code obtained from the file name, e.g. locales/es.json -> lang code: es.

How to use it?

Put the texts in the original language inside the function of vue-i18n, for example:

<!-- Single or double quote, and template literals -->
<p>{{ $t('Hello World') }} {{ $t("Hello, how are you?") }} {{ $t(`Hey. I'm watching you!`) }}</p>

<!-- *Note: to be able to use it in tags or when we send text to a component, we must use the single quote format
and bind it to the attribute. -->

<MyComponent :text="$t('example text')" />

<b-form-input v-model="name" type="text" :placeholder="$t('Name')"></b-form-input>

// In TS:
<script setup lang="ts">
  import { useI18n } from 'vue-i18n'

  const { t } = useI18n()
  t('This is an example')
</script>

You may have noticed that we don't use translations keys like: greetings.hello, the reason is that defining keys is a troublesome task, and keys doesn't always show what we want to display, take this translation file for example:

// es.json

{
  "greetings": {
    "hello": "Hola, ¿cómo estás?."
  }
}

And the corresponding translation usage:

// Component.vue

t('greetings.hello')

By just looking at the translation key, we won't know what the original text was, now look a this example:

// es.json

{
  "Hello, how are you?": "Hola, ¿cómo estás?."
}
// Component.vue

$t('Hello, how are you?')

Better right?, we can directly see the original text, and it's much simpler to translate, we also won't need to define keys because the original text is the key!.

Browser language detection

The default language would match the language of the browser, in case the language is not supported by the application, the fallback language en would be activated.

Vue i18n extract

Manually extracting the texts from vue or js,ts files is a complex task, we are often lazy to do so or we forget to add them, therefore we lose the sync between the translations files and the source code, that's why we use vue-i18n-extract, a handy tool that runs static analysis of the source code files and extracts the translation texts from the source code and add them to the translations files like es.json, en.json, de.json, etc. It no only adds the missing keys but also with a command we can remove the no longer used translations.

To extract the keys/original text into the translations files, run:

npm run vue-i18n-extract

This executes the command located in package.json, which will search for the keys in the vue files given, compare it with the files inside the lang folder and if it finds new words, it will add them.

This script uses the vue-i18n-extract.config.js file for its configuration. This file is located in the root of the project.

Adding a new language:

To add a new language, for instance the German language, just create its file inside the locales folder using its language code, example: ./locales/de.json. Then run npm run vue-i18n-extract to populate the translation keys into that file.

IMPORTANT: When creating the file, make it a valid JSON file, then at least it must has {}, otherwise the extraction would fail.

Example:

// locales/es.json

{
}

The file would be loaded automatically by vite, a vite restart may be needed.

Removing unused translations

In case you want to remove the keys that are in the translation files but are not being used in the vue files, you can run:

npm run vue-i18n-extract-remove

See:

Recommended IDE Setup

Deployment

Heroku

In Heroku create the app, then configure the following buildpacks in the same order:

  • heroku/jvm
  • heroku/nodejs
  • heroku-community/static

Config the Heroku remote:

heroku login
heroku git:remote -a <app_name>

Finally, push the changes:

git push heroku main

Author: helixsoftco
Source code: https://github.com/helixsoftco/vuelix
License: 

#vue #vuejs #vite #vitejs #typescript 

Vuelix: Vue 3 + Vite Template/framework

Vite Plugin Electron: Integrate Vite and Electron.

vite-plugin-electron

Integrate Vite and Electron 

vite-plugin-electron.gif

Install

npm i vite-plugin-electron -D

Usage

Example 👉 vite-plugin-electron-quick-start

vite.config.ts

import electron from 'vite-plugin-electron'

export default {
  plugins: [
    electron({
      main: {
        entry: 'electron/main.ts',
      },
    }),
  ],
}

API

electron(config: Configuration)

import type { LibraryOptions, UserConfig } from 'vite'
import type { InputOption } from 'rollup'
import type { VitePluginElectronRenderer } from 'vite-plugin-electron-renderer'

export interface CommonConfiguration {
  vite?: UserConfig
  /**
   * Explicitly include/exclude some CJS modules  
   * `modules` includes `dependencies` of package.json, Node.js's `builtinModules` and `electron`  
   */
  resolve?: (modules: string[]) => typeof modules | undefined
}

export interface Configuration {
  main: CommonConfiguration & {
    /**
     * Shortcut of `build.lib.entry`
     */
    entry: LibraryOptions['entry']
  }
  preload?: CommonConfiguration & {
    /**
     * Shortcut of `build.rollupOptions.input`
     */
    input: InputOption
  }
  /**
   * Support use Node.js API in Electron-Renderer
   * @see https://github.com/electron-vite/vite-plugin-electron-renderer
   */
  renderer?: Parameters<VitePluginElectronRenderer>[0]
}

How to work

The plugin is just the encapsulation of the built-in scripts of electron-vite-boilerplate/scripts

Recommend structure

Let's use the vanilla-ts template created based on create vite as an example

+ ├─┬ electron
+ │ └── main.ts
  ├─┬ src
  │ ├── main.ts
  │ ├── style.css
  │ └── vite-env.d.ts
  ├── .gitignore
  ├── favicon.svg
  ├── index.html
  ├── package.json
  ├── tsconfig.json
+ └── vite.config.ts

🚨 By default, the files in electron folder will be built into the dist/electron

Put Node.js packages in dependencies

Electron-Main

In general, Vite may not correctly build Node.js packages, especially C/C++ native modules, but Vite can load them as external packages. So, put your Node.js package in dependencies. Unless you know how to properly build them with Vite.

By default, vite-plugin-electron treats packages in dependencies as external modules. If you don't want this, you can control this behavior with options.resolve().

通常的,Vite 可能不能正确的构建 Node.js 的包,尤其是 C/C++ 原生模块,但是 Vite 可以将它们以外部包的形式加载。所以,请将 Node.js 包放到 dependencies 中。除非你知道如何用 Vite 正确的构建它们。

默认情况下,vite-plugin-electron 会将 dependencies 中的包视为 external 模块。如果你不希望这样,你可以通过 options.resolve() 来控制改行为。

Electron-Renderer

You can see 👉 dependencies vs devDependencies


Author: electron-vite
Source code: https://github.com/electron-vite/vite-plugin-electron
License:

#vite #typescript #electron 

Vite Plugin Electron: Integrate Vite and Electron.
Kevon  Krajcik

Kevon Krajcik

1656752400

Vite Plugin Vue I18n: Integration for Vue I18n

@intlify/bundle-tools

The bundle tools for Vue I18n

📦 Packages

PackageBundlerVersion (click for changelogs)
@intlify/unplugin-vue-i18nvite / webpackunplugin-vue-i18n version
@intlify/vite-plugin-vue-i18nvitevite-plugin-vue-i18n version
@intlify/vue-i18n-loaderwebpackvue-i18n-loader version (for vue-i18n@9.x)
@intlify/rollup-plugin-vue-i18nrolluprollup-plugin-vue-i18n version

💪 Contribution

See Contributing Guide.


Author:  intlify
Source Code: https://github.com/intlify/bundle-tools
License:  MIT license

#typescript #javascript #vite #vue 

 Vite Plugin Vue I18n: Integration for Vue I18n
Fleta  Dickens

Fleta Dickens

1656752400

Rollup Plugin Url: Import Files As Data-URIs Or ES Modules.

@rollup/plugin-url

🍣 A Rollup plugin which imports files as data-URIs or ES Modules.

Requirements

This plugin requires an LTS Node version (v8.0.0+) and Rollup v1.20.0+.

Install

Using npm:

npm install @rollup/plugin-url --save-dev

Usage

Create a rollup.config.js configuration file and import the plugin:

import url from '@rollup/plugin-url';

export default {
  input: 'src/index.js',
  output: {
    dir: 'output',
    format: 'cjs'
  },
  plugins: [url()]
};

Then call rollup either via the CLI or the API.

With an accompanying file src/index.js, the local image.svg file would now be importable as seen below:

// src/index.js
import svg from './image.svg';
console.log(`svg contents: ${svg}`);

Options

exclude

Type: String | Array[...String]
Default: null

A minimatch pattern, or array of patterns, which specifies the files in the build the plugin should ignore. By default no files are ignored.

include

Type: String | Array[...String]
Default: ['**/*.svg', '**/*.png', '**/*.jp(e)?g', '**/*.gif', '**/*.webp']

A minimatch pattern, or array of patterns, which specifies the files in the build the plugin should operate on. By default .svg, .png, .jpg, .jpeg, .gif and .webp files are targeted.

limit

Type: Number
Default: 14336 (14kb)

The file size limit for inline files. If a file exceeds this limit, it will be copied to the destination folder and the hashed filename will be provided instead. If limit is set to 0 all files will be copied.

publicPath

Type: String
Default: (empty string)

A string which will be added in front of filenames when they are not inlined but are copied.

emitFiles

Type: Boolean
Default: true

If false, will prevent files being emitted by this plugin. This is useful for when you are using Rollup to emit both a client-side and server-side bundle.

fileName

Type: String
Default: '[hash][extname]'

If emitFiles is true, this option can be used to rename the emitted files. It accepts the following string replacements:

  • [hash] - The hash value of the file's contents
  • [name] - The name of the imported file (without its file extension)
  • [extname] - The extension of the imported file (including the leading .)
  • [dirname] - The parent directory name of the imported file (including trailing /)

sourceDir

Type: String
Default: (empty string)

When using the [dirname] replacement in fileName, use this directory as the source directory from which to create the file path rather than the parent directory of the imported file. For example:

src/path/to/file.js

import png from './image.png';

rollup.config.js

url({
  fileName: '[dirname][hash][extname]',
  sourceDir: path.join(__dirname, 'src')
});

Emitted File: path/to/image.png

destDir

Type: String
Default: (empty string)

The destination dir to copy assets, usually used to rebase the assets according to HTML files.

Meta

CONTRIBUTING

LICENSE (MIT)


Author: 
Source Code: https://github.com/rollup/plugins/
License: 

#vite #typescript #javascript #Rollup 

Rollup Plugin Url: Import Files As Data-URIs Or ES Modules.
Conor  Grady

Conor Grady

1656748800

Vite Plugin Html Template: HTML Template, Like Html-webpack-plugin

vite-plugin-html-template

HTML template for vite app, like html-webpack-plugin for webpack.

It works perfectly together with vite-plugin-mpa.  

Motivation

  • Vite needs an html entry file, which means we must have
    • projectRoot/index.html for SPA
    • projectRoot/src/pages/*/index.html for MPA
  • Why not use html template for all entries
  • Also we should support ejs/lodash.template syntax for the html content, like setting <title></title>.

Usage

yarn add -D vite-plugin-html-template
// vite.config.ts
import htmlTemplate from 'vite-plugin-html-template'

// @see https://vitejs.dev/config/
export default defineConfig({
  plugins: [
    // ...other plugins
    htmlTemplate(/* options */),
  ],
})

Options

// for SPA, there is nothing to do, just use `public/index.html` as template

// for MPA, customise the template path (default is `public/index.html`) and page title:
{
  // where is the pages' root directory?
  pagesDir: 'src/pages',
  // define pages like it is done in vue-cli
  pages: {
    index: {
      template: './public/index.html',
      title: 'Homepage',
    },
    subpage: {
      template: './src/pages/subpage/index.html',
      title: 'Subpage',
    },
  },
  // expose to template
  data: {
    title: 'Homepage',
  },
}

Underlying

Further


Author: IndexXuan
Source code: https://github.com/IndexXuan/vite-plugin-html-template
License:

#vite #typescript #html 

Vite Plugin Html Template: HTML Template, Like Html-webpack-plugin
Noemi  Hintz

Noemi Hintz

1656748800

Vite Plugin Nunjucks: Vite Plugin for Nunjucks

vite-plugin-nunjucks

Vite plugin for Nunjucks.

Supports:
📂 - Templates and layouts 🔗
📃 - Variables for each entry point (HTML) and global scope
🎠 - Custom filters 🔗 and extensions 🔗

Install

Yarn

yarn add vite-plugin-nunjucks -D

or npm

npm i vite-plugin-nunjucks --save-dev

Usage

Configuration

Use plugin in your Vite config (vite.config.ts)

import nunjucks from 'vite-plugin-nunjucks'

export default {
    plugins: [
        nunjucks(),
    ]
}

Example

Input (src/index.html):

{% extends "src/html/layout.html" %}
{% include "src/html/hello.html"  %}

{% block content %}
    {% if username %}
        Username: {{ username }}
    {% else %}
        Variable <code>username</code> is missing
    {% endif %}
{% endblock %}

Template (src/html/layout.html):

<!DOCTYPE html>
<html lang="en">
<head></head>
<body>
    {% block content %}
    {% endblock %}
</body>
</html>

Template (src/html/hello.html):

<h1>Hello world!</h1>

Vite config (vite.config.ts)

import nunjucks from 'vite-plugin-nunjucks'

export default {
    plugins: [
        nunjucks({ variables: { 'index.html': { username: 'John' }}} ),
    ]
}

Output (dist/index.html)

<!DOCTYPE html>
<html lang="en">
<head></head>
<body>
    <h1>Hello world!</h1>
    Username: John
</body>
</html>

Environment

Since v0.1.4 you can pass custom filters and extensions to the environment.
Config example:

import nunjucks from 'vite-plugin-nunjucks'

export default {
    plugins: [
        nunjucks({
            nunjucksEnvironment: {
                filters: {someFilter: someFilter},
                extensions: {someExtension: SomeExtension}
            }
        }),
    ]
}

Filter should look like this (for more info check the Nunjucks documentation)

const someFilter = (val) => {
    // ... some logic
    return 'My modified filter content';
}

and extension like this:

const SomeExtension = {
    tags: ['something'],
    parse: function(parser, nodes, lexer) {
        const [tag] = this.tags
        const tok = parser.nextToken()
        const args = parser.parseSignature(null, true)
        parser.advanceAfterBlockEnd(tok.value)
        const body = parser.parseUntilBlocks(tag, `end${tag}`)
        parser.advanceAfterBlockEnd()
        return new nodes.CallExtension(this, 'run', args, [body])
    },
    run (args) {
        return 'My modified extension content'
    }
}

then you can use it in the template:

{{ 'some text' | someFilter }}

{% something %}
    Some content
{% endsomething %}

and the result should be:

My modified filter content
My modified extension content

Async filter

If you need asynchronous filter you can pass nunjucksFilter instead of nunjucksFilterCallback:

import nunjucks from 'vite-plugin-nunjucks'

export default {
    plugins: [
        nunjucks({
            nunjucksEnvironment: {
                filters: {someFilter: {
                    async: true,
                    filter: someFilter
                }},
            }
        }),
    ]
}

Own environment

You can use your own environment that you configure entirely

import nunjucks from 'vite-plugin-nunjucks'

const env = new nunjucks.Environment(/* someOptions */)
env.addFilter('someFilter', someFilter);
env.addExtension('someExtension', SomeExtension);
export default {
    plugins: [
        nunjucks({nunjucksEnvironment: env}),
    ]
}

Options

ParameterTypeDefaultDescription
templatesDirstring./src/htmlAbsolute path where are HTML templates located. Example: path.resolve(process.cwd(), 'src', 'myTemplates')
variablesRecord<string, object>{}Variables for each entry point. Example { 'index.html': {username:'John'} }
nunjucksConfigurenunjucks.ConfigureOptions{noCache:true}Configure options for Nunjucks
nunjucksEnvironmentnunjucksEnvironmentOptions OR nunjucks.Environment{noCache:true}Configure Nunjucks environment or pass your own env

Author: Jax-p
Source code: https://github.com/Jax-p/vite-plugin-nunjucks
License: MIT license

#vite #typescript #javascript 

Vite Plugin Nunjucks: Vite Plugin for Nunjucks
Michele  Herman

Michele Herman

1656748800

Unplugin Auto Import: On-demand API Auto-importing For Vite

unplugin-auto-import

Auto import APIs on-demand for Vite, Webpack, Rollup and esbuild. With TypeScript support. Powered by unplugin.


without

import { computed, ref } from 'vue'
const count = ref(0)
const doubled = computed(() => count.value * 2)

with

const count = ref(0)
const doubled = computed(() => count.value * 2)

without

import { useState } from 'react'
export function Counter() {
  const [count, setCount] = useState(0)
  return <div>{ count }</div>
}

with

export function Counter() {
  const [count, setCount] = useState(0)
  return <div>{ count }</div>
}

Install

npm i -D unplugin-auto-import

Vite
 

// vite.config.ts
import AutoImport from 'unplugin-auto-import/vite'

export default defineConfig({
  plugins: [
    AutoImport({ /* options */ }),
  ],
})

Example: playground/

 

 

Rollup
 

// rollup.config.js
import AutoImport from 'unplugin-auto-import/rollup'

export default {
  plugins: [
    AutoImport({ /* options */ }),
    // other plugins
  ],
}

 

 

Webpack
 

// webpack.config.js
module.exports = {
  /* ... */
  plugins: [
    require('unplugin-auto-import/webpack')({ /* options */ }),
  ],
}

 

 

Nuxt
 

You don't need this plugin for Nuxt, it's already builtin.

 

 

Vue CLI
 

// vue.config.js
module.exports = {
  configureWebpack: {
    plugins: [
      require('unplugin-auto-import/webpack')({ /* options */ }),
    ],
  },
}

 

 

Quasar
 

// quasar.conf.js
const AutoImportPlugin = require('unplugin-auto-import/webpack')

module.exports = {
  build: {
    chainWebpack(chain) {
      chain.plugin('unplugin-auto-import').use(
        AutoImportPlugin({ /* options */ }),
      )
    },
  },
}

 

 

esbuild
 

// esbuild.config.js
import { build } from 'esbuild'

build({
  /* ... */
  plugins: [
    require('unplugin-auto-import/esbuild')({
      /* options */
    }),
  ],
})

 

 

Configuration

AutoImport({
  // targets to transform
  include: [
    /\.[tj]sx?$/, // .ts, .tsx, .js, .jsx
    /\.vue$/, /\.vue\?vue/, // .vue
    /\.md$/, // .md
  ],

  // global imports to register
  imports: [
    // presets
    'vue',
    'vue-router',
    // custom
    {
      '@vueuse/core': [
        // named imports
        'useMouse', // import { useMouse } from '@vueuse/core',
        // alias
        ['useFetch', 'useMyFetch'], // import { useFetch as useMyFetch } from '@vueuse/core',
      ],
      'axios': [
        // default imports
        ['default', 'axios'], // import { default as axios } from 'axios',
      ],
      '[package-name]': [
        '[import-names]',
        // alias
        ['[from]', '[alias]'],
      ],
    },
  ],

  // Auto import for all module exports under directories
  dirs: [
    // './hooks',
    // './composables'
    // ...
  ],

  // Filepath to generate corresponding .d.ts file.
  // Defaults to './auto-imports.d.ts' when `typescript` is installed locally.
  // Set `false` to disable.
  dts: './auto-imports.d.ts',

  // Auto import inside Vue template
  // see https://github.com/unjs/unimport/pull/15 and https://github.com/unjs/unimport/pull/72
  vueTemplate: false,

  // Custom resolvers, compatible with `unplugin-vue-components`
  // see https://github.com/antfu/unplugin-auto-import/pull/23/
  resolvers: [
    /* ... */
  ],

  // Generate corresponding .eslintrc-auto-import.json file.
  // eslint globals Docs - https://eslint.org/docs/user-guide/configuring/language-options#specifying-globals
  eslintrc: {
    enabled: false, // Default `false`
    filepath: './.eslintrc-auto-import.json', // Default `./.eslintrc-auto-import.json`
    globalsPropValue: true, // Default `true`, (true | false | 'readonly' | 'readable' | 'writable' | 'writeable')
  },
})

Refer to the type definitions for more options.

Presets

See src/presets.

TypeScript

In order to properly hint types for auto-imported APIs

  1. Enable options.dts so that auto-imports.d.ts file is automatically generated
  2. Make sure auto-imports.d.ts is not excluded in tsconfig.json


 

AutoImport({
  dts: true // or a custom path
})

ESLint

💡 When using TypeScript, we recommend to disable no-undef rule directly as TypeScript already check for them and you don't need to worry about this.

If you have encountered ESLint error of no-undef:

  1. Enable eslintrc.enabled


 

AutoImport({
  eslintrc: {
    enabled: true, // <-- this
  },
})
  1. Update your eslintrc: Extending Configuration Files


 

// .eslintrc.js
module.exports = {
  extends: [
    './.eslintrc-auto-import.json',
  ],
}

FAQ

Compare to unimport

From v0.8.0, unplugin-auto-import uses unimport underneath. unimport is designed to be a lower level tool (it also powered Nuxt's auto import). You can think unplugin-auto-import is a wrapper of it that provides more user-friendly config APIs and capability like resolvers. Development of new features will mostly happend in unimport from now.

Compare to vue-global-api

You can think of this plugin as a successor to vue-global-api, but offering much more flexibility and bindings with libraries other than Vue (e.g. React).

Pros

  • Flexible and customizable
  • Tree-shakable (on-demand transforming)
  • No global population

Cons

  • Relying on build tools integrations (while vue-global-api is pure runtime) - but hey, we have supported quite a few of them already!

Author: antfu
Source code: https://github.com/antfu/unplugin-auto-import
License: MIT license

#vite #typescript 

Unplugin Auto Import: On-demand API Auto-importing For Vite
Fleta  Dickens

Fleta Dickens

1656743535

Rollup Plugin Wasm: Import WebAssembly Code with Rollup

@rollup/plugin-wasm

🍣 A Rollup which allows importing and bundling WebAssembly modules.

WebAssembly Modules are imported asynchronous as base64 strings. Small modules can be imported synchronously.

Requirements

This plugin requires an LTS Node version (v8.0.0+) and Rollup v1.20.0+.

Install

Using npm:

npm install @rollup/plugin-wasm --save-dev

Usage

Create a rollup.config.js configuration file and import the plugin:

import { wasm } from '@rollup/plugin-wasm';

export default {
  input: 'src/index.js',
  output: {
    dir: 'output',
    format: 'cjs'
  },
  plugins: [wasm()]
};

Then call rollup either via the CLI or the API.

Options

sync

Type: Array[...String]
Default: null

Specifies an array of strings that each represent a WebAssembly file to load synchronously. See Synchronous Modules for a functional example.

maxFileSize

Type: Number
Default: 14336 (14kb)

The maximum file size for inline files. If a file exceeds this limit, it will be copied to the destination folder and loaded from a separate file at runtime. If maxFileSize is set to 0 all files will be copied.

Files specified in sync to load synchronously are always inlined, regardless of size.

publicPath

Type: String
Default: (empty string)

A string which will be added in front of filenames when they are not inlined but are copied.

targetEnv

Type: "auto" | "browser" | "node"
Default: "auto"

Configures what code is emitted to instantiate the Wasm (both inline and separate):

  • "auto" will determine the environment at runtime and invoke the correct methods accordingly
  • "auto-inline" always inlines the Wasm and will decode it according to the environment
  • "browser" omits emitting code that requires node.js builtin modules that may play havoc on downstream bundlers
  • "node" omits emitting code that requires fetch

WebAssembly Example

Given the following simple C file:

int main() {
  return 42;
}

Compile the file using emscripten, or the online WasmFiddle tool. Then import and instantiate the resulting file:

import sample from './sample.wasm';

sample({ ...imports }).then(({ instance }) => {
  console.log(instance.exports.main());
});

The WebAssembly is inlined as a base64 encoded string. At runtime the string is decoded and a module is returned.

Note: The base64 string that represents the WebAssembly within the bundle will be ~33% larger than the original file.

Synchronous Modules

Small modules (< 4KB) can be compiled synchronously by specifying them in the configuration.

wasm({
  sync: ['web/sample.wasm', 'web/foobar.wasm']
});

This means that the exports can be accessed immediately.

import sample from './sample.wasm';

const instance = sample({ ...imports });

console.log(instance.exports.main());

Meta

CONTRIBUTING

LICENSE (MIT)


Author: 
Source Code: https://github.com/rollup/plugins/
License: 

#vite #typescript #javascript #Rollup #WebAssembly  

Rollup Plugin Wasm: Import WebAssembly Code with Rollup
Conor  Grady

Conor Grady

1656741600

Vite Plugin Html Config: HTML Tag Configuration

vite-plugin-html-config

This plugin helps us configure additional html

The plugin is based on vite transformIndexHtml hooks.

If we want to distinguish the environment and introduce resources in index.html, we can use this plugin. stand by, favicon url, metas config, link tag config, style tag config, headScripts config,body script config.

Install

node version: >=12.0.0

vite version: >=2.0.0

yarn add vite-plugin-html-config -D

Options

  • favicon : html favicon url (href url)
  • metas : html meta tag, such as key=xx,value=xxx
  • links : html head link tag
  • style : html style string
  • headScripts : html head script
  • scripts : html script with body tag

Usage

// vite.config.js
import htmlPlugin from 'vite-plugin-html-config';

const htmlPluginOpt = {
  favicon: './logo.svg',
  headScripts: [
    `var msg = 'head script'
     console.log(msg);`,
    {
      async: true,
      src: 'https://abc.com/b.js',
      type: 'module'
    },
    { content: `console.log('hello')`, charset: 'utf-8' }
  ],
  scripts: [
    `var msg = 'body script'
     console.log(msg);`,
    {
      async: true,
      src: 'https://abc.com/b.js',
      type: 'module'
    }
  ],
  metas: [
    {
      name: 'keywords',
      content: 'vite html meta keywords'
    },
    {
      name: 'description',
      content: 'vite html meta description'
    },
    {
      bar: 'custom meta'
    }
  ],
  links: [
    {
      rel: 'stylesheet',
      href: './style.css'
    },
    {
      rel: 'modulepreload',
      href: 'https://cn.vitejs.dev/assets/guide_api-plugin.md.6884005a.lean.js'
    }
  ],
  style: `body { color: red; };*{ margin: 0px }`
}

module.exports = {
  plugins: [htmlPlugin(htmlPluginOpt)]
}

Example

We can inject different scripts through different environments

such as:script in head,script in body and more.

in config file

// vite.config.js

const headScripts = []

// from app env
const APP_ENV = 'pro'

const BAIDU_KEY = APP_ENV==='pro'?'123123':'xxxxxx'

if (APP_ENV === 'pro') {
  headScripts.push(
    {
      src: 'https://xxxxxxx/mito.js',
      apikey: '123123123123123',
      crossorigin: 'anonymous',
    },
    {
      src: 'https://bbbbb.js',
    },
  )
}

const htmlPluginOpt = {
  headScripts,
  metas: [
    {
      name: 'keywords',
      content: 'vite html meta keywords',
    },
    {
      name: 'description',
      content: 'vite html meta description',
    },
  ],
  links: [
    {
      rel: 'stylesheet',
      href: './style.css',
    },
    {
      rel: 'modulepreload',
      href: 'https://www.google.com/xxx.js',
    },
  ],
  scripts:[
    `var _hmt = _hmt || [];
(function() {
  var hm = document.createElement("script");
  hm.src = "https://hm.baidu.com/hm.js?${BAIDU_KEY}";
  var s = document.getElementsByTagName("script")[0]; 
  s.parentNode.insertBefore(hm, s);
})();`
  ],
  style: 'body { color: red; };*{ margin: 0px }',
}
module.exports = {
  plugins: [htmlPlugin(htmlPluginOpt)]
}

build index.html

<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Vite React</title>
    <meta name="keywords" content="vite html meta keywords">
    <meta name="description" content="vite html meta description">
    <link rel="stylesheet" href="./style.css">
    <link rel="modulepreload" href="https://www.google.com/xxx.js">
    <style>  body { color: red; };*{ margin: 0px }</style>
    <script src="https://xxxxxxx/mito.js" apikey="123123123123123" crossorigin="anonymous" customTag=""></script>
    <script src="https://bbbbb.js"></script>
  </head>
  <body>
    <div id="root"></div>
    <script>var _hmt = _hmt || [];
(function() {
  var hm = document.createElement("script");
  hm.src = "https://hm.baidu.com/hm.js?123123";
  var s = document.getElementsByTagName("script")[0]; 
  s.parentNode.insertBefore(hm, s);
})();</script>
  </body>
</html>

other example

https://github.com/saschazar21/jpeg-butcher/blob/main/vite.config.ts#L30


Author: ahwgs
Source code: https://github.com/ahwgs/vite-plugin-html-config
License: MIT license

#vite #html #typescript 

Vite Plugin Html Config: HTML Tag Configuration
Kevon  Krajcik

Kevon Krajcik

1656741600

Vite SSG: Static Site Generation for Vue 3 on Vite

Vite SSG

Static-site generation for Vue 3 on Vite.

ℹ️ Vite 2 is supported from v0.2.x, Vite 1's support is discontinued.

Install

This library requires Node.js version >= 14

npm i -D vite-ssg vue-router @vueuse/head

// package.json
{
  "scripts": {
    "dev": "vite",
-   "build": "vite build"
+   "build": "vite-ssg build"
  }
}
// src/main.ts
import { ViteSSG } from 'vite-ssg'
import App from './App.vue'

// `export const createApp` is required instead of the original `createApp(App).mount('#app')`
export const createApp = ViteSSG(
  // the root component
  App,
  // vue-router options
  { routes },
  // function to have custom setups
  ({ app, router, routes, isClient, initialState }) => {
    // install plugins etc.
  },
)

Single Page SSG

To have SSG for the index page only (without vue-router), import from vite-ssg/single-page instead, and you only need to install npm i -D vite-ssg @vueuse/head.

// src/main.ts
import { ViteSSG } from 'vite-ssg/single-page'
import App from './App.vue'

// `export const createApp` is required instead of the original `createApp(App).mount('#app')`
export const createApp = ViteSSG(App)

<ClientOnly/>

Component ClientOnly is registered globally along with the app creation.

<client-only>
  <your-client-side-components />
</client-only>

Document head

From v0.4.0, we ship @vueuse/head to manage the document head out-of-box. You can directly use it in your pages/components, for example:

<template>
  <button @click="count++">Click</button>
</template>

<script setup>
import { useHead } from '@vueuse/head'

useHead({
  title: 'Website Title',
  meta: [
    {
      name: `description`,
      content: `Website description`,
    },
  ],
})
</script>

That's all, no configuration is needed. Vite SSG will handle the server-side rendering and merging automatically.

Refer to @vueuse/head's docs for more usage about useHead.

Critical CSS

Vite SSG has built-in support for generating Critical CSS inlined in the HTML via the critters package. Install it via:

npm i -D critters

Critical CSS generation will be enabled automatically for you.

Initial State

The initial state comprises data that is serialized to your server-side generated HTML that is hydrated in the browser when accessed. This data can be data fetched from a CDN, an API, etc, and is typically needed as soon as the application starts or is accessed for the first time.

The main advantage of setting the application's initial state is that the statically generated pages do not need to fetch the data again as the data is fetched during build time and serialized into the page's HTML.

The initial state is a plain JavaScript object that can be set during SSR, i.e., when statically generating the pages, like this:

// src/main.ts

// ...

export const createApp = ViteSSG(
  App,
  { routes },
  ({ app, router, routes, isClient, initialState }) => {
    // ...

    if (import.meta.env.SSR) {
      // Set initial state during server side
      initialState.data = { cats: 2, dogs: 3 }
    }
    else {
      // Restore or read the initial state on the client side in the browser
      console.log(initialState.data) // => { cats: 2, dogs: 3 }
    }

    // ...
  },
)

Typically, you will use this with an application store, such as Vuex or Pinia. For examples, see below:

When using Pinia

Following [Pinia's guide](https://pinia.esm.dev/ssr), you will to adapt your `main.{ts,js}` file to look like this:

// main.ts
import { ViteSSG } from 'vite-ssg'
import { createPinia } from 'pinia'
import routes from 'virtual:generated-pages'
// use any store you configured that you need data from on start-up
import { useRootStore } from './store/root'
import App from './App.vue'

export const createApp = ViteSSG(
  App,
  { routes },
  ({ app, router, initialState }) => {
    const pinia = createPinia()
    app.use(pinia)

    if (import.meta.env.SSR)
      initialState.pinia = pinia.state.value
    else
      pinia.state.value = initialState.pinia || {}

    router.beforeEach((to, from, next) => {
      const store = useRootStore(pinia)
      if (!store.ready)
        // perform the (user-implemented) store action to fill the store's state
        store.initialize()
      next()
    })
  },
)

 

When using Vuex

 

// main.ts
import { ViteSSG } from 'vite-ssg'
import routes from 'virtual:generated-pages'
import { createStore } from 'vuex'
import App from './App.vue'

// Normally, you should definitely put this in a separate file
// in order to be able to use it everywhere
const store = createStore({
  // ...
})

export const createApp = ViteSSG(
  App,
  { routes },
  ({ app, router, initialState }) => {
    app.use(store)

    if (import.meta.env.SSR)
      initialState.store = store.state
    else
      store.replaceState(initialState.store)

    router.beforeEach((to, from, next) => {
      // perform the (user-implemented) store action to fill the store's state
      if (!store.getters.ready)
        store.dispatch('initialize')

      next()
    })
  },
)

 

For the example of how to use a store with an initial state in a single page app, see the single page example.

State Serialization

Per default, the state is deserialized and serialized by using JSON.stringify and JSON.parse. If this approach works for you, you should definitely stick to it as it yields far better performance.

You may use the option transformState in the ViteSSGClientOptions as displayed below. A valid approach besides JSON.stringify and JSON.parse is @nuxt/devalue (which is used by Nuxt.js):

import devalue from '@nuxt/devalue'
import { ViteSSG } from 'vite-ssg'
// ...
import App from './App.vue'

export const createApp = ViteSSG(
  App,
  { routes },
  ({ app, router, initialState }) => {
    // ...
  },
  {
    transformState(state) {
      return import.meta.env.SSR ? devalue(state) : state
    },
  },
)

A minor remark when using @nuxt/devalue: In case, you are getting an error because of a require within the package @nuxt/devalue, you have to add the following piece of config to your Vite config:

// vite.config.ts
// ...

export default defineConfig({
  resolve: {
    alias: {
      '@nuxt/devalue': '@nuxt/devalue/dist/devalue.js',
    },
  },
  // ...
})

Async Components

Some applications may make use of Vue features that cause components to render asynchronously (e.g. suspense). When these features are used in ways that can influence initialState, the onSSRAppRendered may be used in order to ensure that all async operations have finished as part of the initial application render:

const { app, router, initialState, isClient, onSSRAppRendered } = ctx

const pinia = createPinia()
app.use(pinia)

if (isClient) {
  pinia.state.value = (initialState.pinia) || {}
}
else {
  onSSRAppRendered(() => {
    initialState.pinia = pinia.state.value
  })
}

Configuration

You can pass options to Vite SSG in the ssgOptions field of your vite.config.js

// vite.config.js

export default {
  plugins: [],
  ssgOptions: {
    script: 'async',
  },
}

See src/types.ts. for more options available.

Custom Routes to Render

You can use the includedRoutes hook to exclude/include route paths to render, or even provide some complete custom ones.

// vite.config.js

export default {
  plugins: [],
  ssgOptions: {
    includedRoutes(paths, routes) {
      // exclude all the route paths that contains 'foo'
      return paths.filter(i => !i.includes('foo'))
    },
  },
}
// vite.config.js

export default {
  plugins: [],
  ssgOptions: {
    includedRoutes(paths, routes) {
      // use original route records
      return routes.flatMap((route) => {
        return route.name === 'Blog'
          ? myBlogSlugs.map(slug => `/blog/${slug}`)
          : route.path
      })
    },
  },
}

Alternatively, you may export the includedRoutes hook from your server entry file. This will be necessary if fetching your routes requires the use of environment variables managed by Vite.

// main.ts

import { ViteSSG } from 'vite-ssg'
import App from './App.vue'

export const createApp = ViteSSG(
  App,
  { routes },
  ({ app, router, initialState }) => {
    // ...
  },
)
export async function includedRoutes(paths, routes) {
  // Sensitive key is managed by Vite - this would not be available inside
  // vite.config.js as it runs before the environment has been populated.
  const apiClient = new MyApiClient(import.meta.env.MY_API_KEY)

  return Promise.all(
    routes.flatMap(async (route) => {
      return route.name === 'Blog'
        ? (await apiClient.fetchBlogSlugs()).map(slug => `/blog/${slug}`)
        : route.path
    }),
  )
}

Comparsion

Use Vitepress when you want:

  • Zero config, out-of-box
  • Single-purpose documentation site
  • Lightweight (No double payload)

Use Vite SSG when you want

  • More controls on the build process and tooling
  • The flexible plugin systems
  • Multi-purpose application with some SSG to improve SEO and loading speed

Cons:

  • Double payload

Example

See Vitesse

Thanks to the prior work

Contribution

Please refer to https://github.com/antfu/contribute


Author:  antfu
Source Code:  https://github.com/antfu/vite-ssg
License:  MIT license

#vite #vue #typescript #javascript 

Vite SSG: Static Site Generation for Vue 3 on Vite

Mithril Ts Vite Starter: Template for Mithril Projects with TypeScript

Mithril with TypeScript Vite Starter

Vite starter template to scaffold a new Mithril with TypeScript project.

This is an unopinionated template; aside from Mithril, TypeScript and Vite, the rest of your project's tools are entirely up to you.

Installation

Pull the template files with degit and install dependencies.

npx degit ArthurClemens/mithril-ts-vite-starter my-project
cd my-project
npm install

npm scripts

  • npm run dev - Starts the development server at port 3000
  • npm run build - Builds the application
  • npm run preview - Serves the build files locally at port 5000

Using JSX

Uncomment the esbuild configuration in vite.config.js.

Example App.tsx:

import m from "mithril";
import "./App.css";

export const App = () => {
  // Local state ...
  return {
    view: () => {
      return (
        <>
          <h1>My Mithril App</h1>
        </>
      );
    },
  };
};

See also


Author: ArthurClemens
Source code: https://github.com/ArthurClemens/mithril-ts-vite-starter
License:

#vite #typescript 

Mithril Ts Vite Starter: Template for Mithril Projects with TypeScript
Noemi  Hintz

Noemi Hintz

1656738000

Vite Plugin Shared Modules: Share Node_modules in Monorepos.

vite-plugin-shared-modules  

Share node_modules in monorepos. Best friend for pnpm's module isolation and module singletons sharing.

Use it as simple as:

// vite.config.ts
import { defineConfig } from 'vite';
import sharedModulesPlugin from 'vite-plugin-shared-modules'
import tsconfigPaths from 'rollup-plugin-tsconfig-paths';

export default defineConfig({
  plugins: [
    sharedModulesPlugin({
      packageName: '@monorepo/shared',
    }),
    // necessary for resolving modules in `node_modules`
    tsconfigPaths({
      // specify the project's tsconfig.json, which configured paths mapping.
      tsConfigPath: join(__dirname, '../../tsconfig.json')
    }),
  ]
});

then you can import singletons by this way:

import foo from '@monorepo/shared/foo'
import bar from '@monorepo/shared/bar'

is equivalent to

import foo from '@monorepo/shared/node_modules/foo'
import bar from '@monorepo/shared/node_modules/bar'

moreover for getting type-safe, add tsconfig paths mapping:

// tsconfig.json
{
    "compilerOptions": {
        "baseUrl": ".",
            "paths": {
                "@monorepo/shared/*": ["./packages/shared/node_modules/*", "./packages/shared/node_modules/@types/*"]
            }
    }
}

the example above we assume the package @monorepo/shared is located under ./packages/shared.


Full Option

The plugin options signatures:

export type SharedModulesPluginOption = {
  packageName: string,
  subpath?: string,
  nodeModules?: string,
  sourceMap?: boolean,
}

The default options:

export const defaultSharedModules = {
  subpath: '',
  nodeModules: 'node_modules',
  sourceMap: true,
}

Author: zheeeng
Source code: https://github.com/zheeeng/vite-plugin-shared-modules
License:

#vite #typescript #javascript 

Vite Plugin Shared Modules: Share Node_modules in Monorepos.
Michele  Herman

Michele Herman

1656738000

Vite Plugin Vars Modifier: A Vite Plugin for Parse Preprocessor File

vite-plugin-vars-modifier

A Plugins for convert variables from css preprocessor file.


English | 中文

Usage

Install

$> npm install vite-plugin-vars-modifier -D
#or
$> yarn add vite-plugin-vars-modifier -D

Use

Add following options in vite.config.js

import modifier from 'vite-plugin-vars-modifier';

export default {
    plugins: [
        modifier({
            paths: ['path/to/file'],
            type: 'less',
        }),
    ],
};

Options

export interface ModifierOptions {
    /**
     * paths for content to pass to parser.
     *
     * support glob format
     *
     * @see https://github.com/mrmlnc/fast-glob#readme
     */
    paths: string | string[];

    /**
     * Whether to remove the prefix
     *
     * @default true
     */
    strip: boolean;

    /**
     * Typeof parser of modifier
     */
    type: 'less' | 'scss';
}

relation


Author: fanhaoyuan
Source code: https://github.com/fanhaoyuan/vite-plugin-vars-modifier
License: MIT license

#vite #typescript 

Vite Plugin Vars Modifier: A Vite Plugin for Parse Preprocessor File