Vite official documentation: cn.vitejs.dev/

Vuex official document: vuex.vuejs.org/zh/

Vuex-module-decorators: github.com/championswi…

preface

We recently used vuex-module-decorators to write projects. It works well with vuue-CLI (webpack) projects, but we are having some problems with Vite.

The main function of the vuex-module-decorators package is to write vuex in TypeScript and decorators. The advantage of this package is that it has more type hints and is much easier to use than native Vuex. Here’s an example from the official document

interface StoreType {
  mm: MyModule
}
// Declare empty store first
const store = new Vuex.Store<StoreType>({})

// Create module later in your code (it will register itself automatically)
// In the decorator we pass the store object into which module is injected
// NOTE: When you set dynamic true, make sure you give module a name
@Module({ dynamic: true.store: store, name: 'mm' })
class MyModule extends VuexModule {
  count = 0

  @Mutation
  incrCount(delta) {
    this.count += delta
  }
}
Copy the code

Found the problem

Next I’ll talk about why vuex-module-decorators work well with vuE-CLI (webpack) constructs.

The reason is webPack’s hot update mechanism.

In Webpack, if CSS is modified, it is a hot update without refreshing the page, and if JS is modified, the page is refreshed and reloaded. That said, the problem with Vuex-module-decorators not supporting hot updates is covered by Webpack.

In Vite, when the source code changes, only necessary parts are updated, so the entire page is not reloaded, but because vuex-module-decorators do not support hot updates, there are problems with duplicate registration of vuex Modules. The following warning appears on the console.

[vuex] duplicate namespace  "app" for the namespaced module
Copy the code

To solve the problem

Since the original project had fallen into disrepair, a branch was forked.

The original project is written in TypeScript, and the good type hints make it quickly readable to people who haven’t touched the project before.

Of course, there is no need to understand the whole project, just find out how the Vuex Module is registered.

Looking through the source code, I found the following:

// src/module/index.ts
function registerDynamicModule<S> (module: Mod<S, any>, modOpt: DynamicModuleOptions) {
  if(! modOpt.name) {throw new Error('Name of module not provided in decorator options')}if(! modOpt.store) {throw new Error('Store not provided in decorator options when using dynamic option')
  }

  modOpt.store.registerModule(
    modOpt.name, // TODO: Handle nested modules too in future
    module,
    { preserveState: modOpt.preserveState || false})}Copy the code

Here is the source code for vuex-module-decorators registering DynamicModule, and notice that there is no handling of hot updates at all.

By looking at the Vuex documentation and vite documentation, I found that Vuex supports hot updates, so I just need to be compatible with Vite.

The modified code is as follows:

function registerDynamicModule<S> (dynamicModule: Mod<S, any>, modOpt: DynamicModuleOptions) {
  if(! modOpt.name) {throw new Error('Name of module not provided in decorator options')}if(! modOpt.store) {throw new Error('Store not provided in decorator options when using dynamic option')}if (import.meta.hot) { // Conditional guards are required so that code can be tree-shaking optimized in production
    // Vite hot update
    if (modOpt.store.hasModule(modOpt.name)) {
      // Hot update if duplicate modules are encountered
      modOpt.store.hotUpdate({
        modules: {
          [modOpt.name]: dynamicModule
        }
      })
      return
    }
    modOpt.store.registerModule(modOpt.name, dynamicModule, {
      preserveState: modOpt.preserveState || false
    })
    return
  }
  modOpt.store.registerModule(modOpt.name, dynamicModule, {
    preserveState: modOpt.preserveState || false})}Copy the code

Update dependencies in the project after running, there is no warning, page status is not lost, the modification is successful.

The modified package has been posted to GitHub at github.com/CaoMeiYouRe…

I am too lazy to publish to NPM, so I download it directly from GitHub.

The usage method is as follows:

// package.json
{
    "dependencies": {
         "vuex-module-decorators": "CaoMeiYouRen/vuex-module-decorators"}}/ / or "vuex - the module - the decorators" : "git+https://github.com/CaoMeiYouRen/vuex-module-decorators.git", too, making access to slow mirror can be used
Copy the code

Compatible webpack

I should have left it there, but then I took a look at what was going on in WebPack.

Hot does not exist in CJS, so the code above should look like this if it is webpack compatible.

function registerDynamicModule<S> (dynamicModule: Mod<S, any>, modOpt: DynamicModuleOptions) {
  if(! modOpt.name) {throw new Error('Name of module not provided in decorator options')}if(! modOpt.store) {throw new Error('Store not provided in decorator options when using dynamic option')}if (module.hot) { // Change this to module.hot to support webpack hot updates.
    // Vite hot update
    if (modOpt.store.hasModule(modOpt.name)) {
      // Hot update if duplicate modules are encountered
      modOpt.store.hotUpdate({
        modules: {
          [modOpt.name]: dynamicModule
        }
      })
      return
    }
    modOpt.store.registerModule(modOpt.name, dynamicModule, {
      preserveState: modOpt.preserveState || false
    })
    return
  }
  modOpt.store.registerModule(modOpt.name, dynamicModule, {
    preserveState: modOpt.preserveState || false})}Copy the code

You can also use the original

Author: Yohito Kusami

This paper addresses: blog. Cmyr. LTD/archives / 12…

Copyright Notice: Reprint please indicate the source!