background
In the article “Three Methods for Common Components of Front-end Multiple VUE Projects (Recommended introduction of NPM File)”, the method of NPM introducing public packages through file is discussed, but there will be many pits in practical application. Here are two problems encountered by the author and the solutions are given.
Problem a
NPM does not automatically install dependencies for packages imported through file. For example, project A imports package B in file mode, as shown below. Package. json in project A:
{
"name": "A"."version": "0.1.0 from"."dependencies": {
"B": "file:.. /B"
}
/ /...
}
Copy the code
Package. json for project B:
{
"name": "B"."version": "0.1.0 from"."dependencies": {
"axios": "^ 0.19.2"
}
/ /...
}
Copy the code
So when NPM install is executed in project A, the AXIOS package is not installed, and there is only one B in node_modules that is introduced via A soft link.
The solution
Main ideas:
- Add a WebPack plugin, DepPlugin, and execute the plugin after the entryOption hook, just after WebPack has processed the configuration item.
- Read all dependencies in the package.json file in dependencies. Read all dependencies in the NPM package in dependencies.
- Install all dependencies above at once, execute
NPM install [email protected] [email protected] [email protected] --no-save
(A, B, and c are the names of dependency packages).
Here is the code: vue.config.js
chainWebpack: config= > {
const depPlugin = require('./plugin/DepPlugin')
config.plugin('DepPlugin').use(depPlugin).tap(args= > args)
}
Copy the code
DepPlugin.js
'use strict'
const path = require('path')
const sep = path.sep
let cwd = process.cwd()
const execSync = require('child_process').execSync
function DepPlugin (options) {
this.options = options || {}
this.done = false
}
DepPlugin.prototype.apply = function (compiler) {
const that = this
compiler.hooks.entryOption.tap('DepPlugin'.compiler= > {
if(that.done) return
const mainDependency = getDependency('. ' + sep + 'package.json')
// Suppose file introduces two items, baqi and Baqi-chat
letsubDependency = { ... getSubDependency('baqi'),
...getSubDependency('baqi-chat')}const subDependencyKey = Object.keys(subDependency)
const mainDependencyKey = Object.keys(mainDependency)
// Get the dependencies in the current package
// Look for dependencies in baqi, baqi-chat, but not in the main package
for (let i = 0; i < subDependencyKey.length; i++) {
if (mainDependencyKey.includes(subDependencyKey[i])) {
delete subDependency[subDependencyKey[i]]
}
}
// Install these dependencies
execCmdSync('cd ' + cwd)
let str = ' '
for (let dep in subDependency) {
// install node_modules without these packages
if (fs.existsSync(path.join(cwd, 'node_modules' + sep + dep)) === false) {
str += dep + The '@' + subDependency[dep].replace(/\"|\^|\~/g.' ') + ' '}}if (str) {
execCmdSync('npm install ' + str + '--no-save')}}}function getSubDependency (moduleName) {
const filePath = path.join(cwd, '.. ' + sep + moduleName + sep + 'package.json')
const dependencies = getDependency(filePath)
return dependencies
}
function getDependency (packageJsonPath) {
const fileObj = JSON.parse(readPackageJson(packageJsonPath))
const dependency = fileObj.dependencies
return dependency
}
function readPackageJson (packageJsonPath) {
const fileStr = fs.readFileSync(packageJsonPath, 'utf8')
return fileStr
}
function execCmdSync (cmdStr) {
console.log('Execute:' + cmdStr)
const out = execSync(cmdStr, { encoding: 'utf8' })
return out
}
Copy the code
Question 2
Babel does not automatically escape packages imported by file, which means that subpackages with ES6 writing in them will report an error when running in older browsers.
The solution
The vUE website describes it this waySo, you can add it in vue.config.js
transpileDependencies: [
/[/\\]node_modules[/\\]baqi[/\\]/./[/\\]node_modules[/\\]baqi-chat[/\\]/
]
Copy the code
The same problem applies to the NPM link