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