preface

Yesterday evening, I am proudly harvest of everyone’s praise at the same time I was watching IG vs Ra (IG is really not line, I saw a comment on the question I introduced this on-demand, I don’t think so, because old yan recently just collected lots of data are so on-demand introduction, later, I decided to watch the game, run test, It doesn’t work on demand (because the resource size doesn’t change whether you pack “on demand” or “off demand”). In the old strict to carefully scrape the information and review the documentation is found how to do the right way to introduce on demand

Thanks again to @Qingyang for pointing out this problem to me, and sorry for not testing this on-demand introduction

Look at the problem

We got the code “laoyan-UI” package

Our packaged lib directory

Element’s packaged directory

This is vant’s packaged lib content

Obviously each of these are components

So that’s all we have to do

Configuration package

The new file

Create a config folder in the root directory

Then create two files in config: config.dev.js and config.build.js

It so long

config.dev.js

We then migrated the contents of vue.config.js to config.dev.js

module.exports = {
    pages: {
        index: {
            entry: 'examples/main.js'.template: 'public/index.html'.filename: 'index.html'}},chainWebpack: config= > {
        config.module
            .rule('js')
            .include
            .add('/packages')
            .end()
            .use('babel')
            .loader('babel-loader')
            .tap(options= > {
                return options
            })
    }
}
Copy the code

config.build.js

Put the code directly into config.build.js

This code is the core on demand

const fs = require('fs');
const path = require('path');
const join = path.join;
// Get the target file based on the current path
const resolve = dir= > path.join(__dirname, '.. / ', dir);

function getComponentEntries(path) {
    let files = fs.readdirSync(resolve(path));

    const componentEntries = files.reduce((fileObj, item) = > {
        // File path
        const itemPath = join(path, item);
        // In the folder
        const isDir = fs.statSync(itemPath).isDirectory();
        const [name, suffix] = item.split('. ');

        // The entry file in the file
        if (isDir) {
            fileObj[item] = resolve(join(itemPath, 'index.js'));
        }
        // The entry file outside the folder
        else if (suffix === 'js') {
            fileObj[name] = resolve(`${itemPath}`);
        }
        return fileObj;
    }, {});

    return componentEntries;
}

const buildConfig = {
    // Output file directory
    outputDir: resolve('lib'),
    productionSourceMap: false./ / webpack configuration
    configureWebpack: {
        // Import file
        entry: getComponentEntries('packages'),
        // Output configuration
        output: {
            // File name
            filename: '[name]/index.js'.// Build the dependency type
            libraryTarget: 'umd'.// The exported item in the library
            libraryExport: 'default'.// The dependency name for the reference
            library: 'laoyan-ui'}},css: {
        sourceMap: false.extract: {
            filename: '[name]/index.css'}},chainWebpack: config= > {
        config.optimization.delete('splitChunks');
        config.plugins.delete('copy');
        config.plugins.delete('preload');
        config.plugins.delete('prefetch');
        config.plugins.delete('html');
        config.plugins.delete('hmr');
        config.entryPoints.delete('app'); }};module.exports = buildConfig;
Copy the code

After copying it in, we’ll import it in vue.config.js

vue.config.js

// Development environment
const devConfig = require('./config/config.dev');
// Package the environment
const buildConfig = require('./config/config.build');
module.exports = process.env.NODE_ENV === 'production' ? buildConfig : devConfig;
Copy the code

You only need to import these two js in vue.config.js

Try packing a bag first

Remember to download the dependencies first

yarn install
Copy the code

This time we will package and use YARN Build directly

yarn build
Copy the code

The packaged components are stored in their respective lib folders

Test it to see if it works

We are still testing components in examples, but we need to modify main.js

  import Vue from 'vue'
  import App from './App.vue'
- import { lyLink } from '.. /lib/index.umd.min.js';
+ import lyLink from '.. /lib/lyLink';
- import '.. /lib/index.css'
+ import '.. /lib/lyLink/index.css'
  Vue.use(lyLink)
  Vue.config.productionTip = false

  new Vue({
    render: h => h(App),
  }).$mount('#app')
Copy the code

So let’s start it up

yarn serve
Copy the code

package.json

Before we publish the package, we need to modify the entry file

{" name ":" laoyan - UI ", "version" : "while", "private" : false,- "main": "lib/index.umd.min.js",
+ "main": "lib/index",
  "scripts": {
    "serve": "vue-cli-service serve",
    "build": "vue-cli-service build"
- "lib": "vue-cli-service build --target lib --name index --dest lib packages/index.js"}, "dependencies" : {" core - js ":" ^ 3.6.5 ", "vue" : "^ 2.6.11"}, "devDependencies" : {" @ vue/cli - plugin - Babel ": "~ 4.5.0 @", "vue/cli - service" : "~ 4.5.0", "node - sass" : "^ 4.12.0", "sass - loader" : "^ 8.0.2", "vue - the template - the compiler" : "^ 2.6.11"}, "browserslist" : [" > 1% ", "the last 2 versions", "not dead"]}Copy the code

Write another component

Before testing, I felt that the way we packaged the test project was useless, because a ly-link component didn’t matter whether you registered globally or not.

So I’m going to add a Ly-button component

Again from the previous chapter, write components in the Packages directory

index.js

lyButton/index.js

import lyButton from './src'

lyButton.install = function (Vue) {
    Vue.component(lyButton.name, lyButton)
}

export default lyButton
Copy the code

index.vue

lyButton/src/index.vue

<template> <! --> <! -- Change the color with the type passed --><a :href="href || undefined" :class="[`ly-link-${type}`]" >
        <! -- Use default slot to fill text -->
        <slot/>
    </a>
</template>

<script>
    export default {
        // we'll use it in index.js
        name:"ly-link".props: {
            // Restrict the type
            href: String.type: {
                type: String.default: 'default'}}}</script>

<style lang="scss" scoped>// Define the link font color.ly-link-default {
        color: # 606266;
    }
    .ly-link-primary {
        color: #409eff;
    }
</style>
Copy the code

Expose the component index.js

packages/index.js

  import lyLink from './lyLink'
+ import lyButton from './lyButton'
  const components = [
      lyLink,
+ lyButton] // Define the install method that accepts Vue as an argument. If you use use to register your plug-in, Const install = function (Vue,opt = {}) {if (install.installed) return // iterate through registered global components Component.map (component => {Vue.component(component.name, component)})} if (typeof window! == 'undefined' && window.vue) {install(window.vue)} export default install export {// The exported object must have install, // The following is a list of specific components, lyLink,+ lyButton
  }
Copy the code

Pack the

yarn build
Copy the code

It is then introduced in examples/main.js

import Vue from 'vue'
import App from './App.vue'
// Import the link component
import lyLink from '.. /lib/lyLink';
// Introduce the button component
import lyButton from '.. /lib/lyButton';
// Introduce the link style
import '.. /lib/lyLink/index.css'
// Introduce the button style
import '.. /lib/lyButton/index.css'

Vue.use(lyLink)
Vue.use(lyButton)

Vue.config.productionTip = false

new Vue({
  render: h= > h(App),
}).$mount('#app')
Copy the code

Introduce the use of ly-button in app. vue

<template>
  <div id="app">
    <ly-link type="primary">Old strict test</ly-link>
    <ly-button type="primary">Old strict test</ly-button>
  </div>
</template>
Copy the code

Start the project

yarn serve
Copy the code

We can see that this effect is ok

We can try global import again

import laoyanUi from '.. /lib/index';
import '.. /lib/index/index.css'
Vue.use(laoyanUi)
Copy the code

So we can start testing the on-demand import effect

But let’s upload NPM first

Remember to change the version number in package.json (e.g. V0.1.1 to at least V0.1.2), otherwise it will not be submitted

npm login
&
npm publish 
Copy the code

Tests are introduced on demand

Create a clean CLI for testing

That’s what it looks like

Component packaging is not introduced

Let’s leave the components out and look at the size of the package

yarn build
Copy the code

Global import component packaging

Install laoyan first – the UI

yarn add laoyan-ui
Copy the code

Introduce the component library in main.js

import Vue from 'vue'
import App from './App.vue'

import laoyanUi from 'laoyan-ui'
import 'laoyan-ui/lib/index/index.css'
Vue.use(laoyanUi)
Vue.config.productionTip = false

new Vue({
  render: h= > h(App),
}).$mount('#app')
Copy the code

Pack again

You can see that there is an extra CSS and app.js with an extra 0.03kib

Try importing on demand

import Vue from 'vue'
import App from './App.vue'

import lyLink from 'laoyan-ui/lib/lyLink/index.js'
import 'laoyan-ui/lib/lyLink/index.css'
Vue.use(lyLink)
Vue.config.productionTip = false

new Vue({
  render: h= > h(App),
}).$mount('#app')
Copy the code

Perform packaging

Js is a bit more than 0.01kib, but CSS is a huge benefit

Is it because there are still too few components? Still have what mistake, hope to have big guy to remind

Configurations are imported on demand

This is too tedious to introduce, say that the user with you such a introduction

Every time you import a component you have to find a folder name you have to import a style, and then you have to register it

Babel-plugin-import is a handy way to do this

First installation

yarn add babel-plugin-import
Copy the code

Configure the Babel. Config. Js

module.exports = {
  presets: ['@vue/cli-plugin-babel/preset'].plugins: [['import',
      {
        libraryName: 'laoyan-ui'.style: (name) = > {
          return `${name}/index.css`;
        },
        camel2DashComponentName: false.// Whether the hump turns short
        camel2UnderlineComponentName: false // Whether the hump needs to be underlined}}]].Copy the code

Delete the main.js import file after configuration

App.vue

<template>
    <div id="app">
        <ly-button>111</ly-button>
    </div>
</template>

<script>
  	/ / introduction
    import { lyButton } from "laoyan-ui";
    export default {
        name: "App"./ / register
        components: { lyButton },
    };
</script>

Copy the code

Effects are ok, what if you need them in more than one place? So let’s go to main.js and configure it, but we just need to import the registration

import Vue from 'vue'
import App from './App.vue'
/ / introduction
import { lyButton } from "laoyan-ui";
/ / register
Vue.use(lyButton)

Vue.config.productionTip = false
new Vue({
  render: h= > h(App),
}).$mount('#app')
Copy the code

The last

If there is still a mistake hope also have a big man to point out

Then thank @Qingyang again

Thank you for reading the likes and comments

data

Test demo and laoyan-UI I put cloud disk

Link: pan.baidu.com/s/1rK9Navx_…

Password: gm16