需求:构建vue组件库成为js sdk 浏览器直接运行
umd是通用格式,兼容各种环境
rollup使用过程中遇到的各种问题
https://www.dazhuanlan.com/2019/10/22/5dae8543f0ec1/
rollup开发依赖包(npm library),解决引入外部依赖失败的有效方法
import nodePolyfills from 'rollup-plugin-node-polyfills';
plugins: [
vue(),
nodePolyfills(),
]
出现这个问题的原因是rollup通过external
+ output.globals
来标记外部依赖,所以需要在配置文件的output输出配置属性中添加globals属性,指定与外部模块相对应的浏览器全局变量名称,如:
globals: {
"vue": "vue" // 指明 global.vue 即是外部依赖 vue
}
要是按照以上配置后问题还没解决,还有一个可能是在引入组件或者自己写js模块时,没有使用相对路径引入,比如你想在 src/index.js
中引入组件 src/components/Test.vue
:
// 应该这样引入
import Test from './components/Test.vue'
// 而不是
import Test from 'components/Test.vue'
(!) Unused external imports
(!) Circular dependencies
this
has been rewritten to undefined
这是因为库中写的代码不正确用了箭头函数然后还绑定了this
,忽略
module is not defined
https://github.com/rollup/rollup/issues/2661
(!) `this` has been rewritten to `undefined`
https://stackoverflow.com/questions/61827807/svelte-i18n-svelte-rollup-compiler-warning-this-has-been-rewritten-to-unde
common.js 在plugin位置尽量在上面,作者本人的插件顺序如下
const plugins = [
vue({
css: true,
compileTemplate: true,
include: /\.vue$/,
target: 'browser',
}),
css(),
nodeResolve({
preferBuiltins: true,
browser: true,
jsnext: true,
main: true,
}),
commonjs(),
alias({
resolve: ['.jsx', '.js', '.vue'], //optional, by default this will just look for .js files or folders
entries: [
{ find: '@', replacement: './package/deleteVersion-vue-build/packages' }, //the initial example
],
}),
nodePolyfills(),
globals(),
replace({
'process.env.NODE_ENV': JSON.stringify(env),
}),
postcss({
modules: false,
extensions: ['.less', '.css', '.scss'],
plugins: [
nested(),
simpleVars(),
cssnext({ warnForDuplicates: false }),
cssnano(),
],
}),
builtins(),
json(),
babel({
exclude: 'node_modules/**',
runtimeHelpers: true,
}),
];
https://github.com/vueComponent/ant-design-vue/issues/2745
npm uninstall babel-plugin-import
WARNING (@babel/preset-env): We noticed you're using the `useBuiltIns` option without declaring a core-js version. Currently, we assume version 2.x when no version is passed. Since this default version will likely change in future versions of Babel, we recommend explicitly setting the core-js version you are using via the `corejs` option.
You should also be sure that the version you pass to the `corejs` option matches the version specified in your `package.json`'s `dependencies` section. If it doesn't, you need to run one of the following commands:
npm install --save core-js@2 npm install --save core-js@3
yarn add core-js@2 yarn add core-js@3
警告(@babel/pre -env):我们注意到你使用了' useBuiltIns '选项而没有声明一个core-js版本。目前,我们假设版本2。x表示没有通过任何版本。因为这个默认版本可能会在Babel的未来版本中改变,我们建议通过“corejs”选项显式设置你正在使用的core-js版本。
您还应该确保传递给“corejs”选项的版本与“包”中指定的版本匹配。json的“依赖性”部分。如果没有,则需要运行以下命令之一:
npm install——save core-js@2 npm install——save core-js@3
yarn add core-js@2 yarn add core-js@3
这个错误定位后发现与rollup-plugin-uglify插件有关,rollup-plugin-uglify不能压缩es6的代码文件。rollup-plugin-uglify的官方文档是说
Note: uglify-js is able to transpile only es5 syntax. If you want to transpile es6+ syntax use terser instead
顺着这个思路有两种解决方法,一只要把es6的代码用babel转换成es5即可。二使用rollup-plugin-terser插件代替rollup-plugin-uglify
安装rollup-plugin-terser
yarn add rollup-plugin-terser --dev
使用rollup-plugin-terser
import { rollup } from "rollup";
import { terser } from "rollup-plugin-terser";
rollup({
input: "main.js",
plugins: [terser()]
});
antd 组件源码错误
switch (e) {
case 'fill':
return c + '-fill';
case 'outline':
return c + '-o';
case 'twotone':
return c + '-twotone';
default:
throw new TypeError('Unknown theme type: ' + e + ', name: ' + c);
}
https://github.com/ant-design/ant-design/issues/19002
注释掉message组件问题消失
default.observable
https://github.com/59naga/babel-plugin-add-module-exports#readme
https://www.jianshu.com/p/b02d4693c40d
index.umd.js:1 Uncaught ReferenceError: require is not defined
rollup开发依赖包(npm library)实战
https://www.jianshu.com/p/2872fbaeb35b
安装最新版rollup
http://www.voidcn.com/article/p-yjriqqee-bqu.html
index.umd.js:1 Uncaught TypeError: Cannot read property 'withScopeId' of undefined
关于Rollup编译vue的插件
npm i -D vue-template-compiler vue-loader rollup-plugin-vue babel-plugin-transform-vue-jsx
在使用Babel去编译代码之前需要进行一些配置,该配置文件需要在src/目录下创建
touch src/.babelrc
内容:
{
"presets": ["es2015-rollup"]
}
在经过上一步配置之后,还需要安装一下babel-preset-es2015-rollup
npm i -D babel-preset-es2015-rollup
上述步骤完成之后我们就可以在文件中使用ES2015特性了,如:
// src/main.js
import { version } from '../package.json';
const message = `current version is ${version}`;
export default () => console.log( message );
最后使用rollup -c打包得出以下结果:
// bundle.js
'use strict';
var version = '1.0.0';
var message = 'current version is ' + version;
var main = (function () {
console.log( message );
});
module.exports = main;
上面 es-2015配置仅供参考,如下是实际使用配置
presets: [
[
'@babel/preset-env',
{
debug: false, // debug,编译的时候 console
useBuiltIns: 'usage', // 按需加载
modules: false, // 模块使用 es modules ,不使用 commonJS 规范
targets: {
node: 'current', // 根据当前节点版本进行编译
},
},
],
],
https://blog.csdn.net/gccll/article/details/52785754
Cannot read property 'extend' of undefined
npm install --save-dev rollup-plugin-clear
在利用webpack的Vue项目中,在main.js中使用import Vue from 'vue' 导入的Vue的包,功能不完善,只是提供了runtime-only的方式,并没有提供像在普通网页中使用Vue那样的功能完善。
包的查找规则
(1)在项目根目录中查找有没有node_modules 的文件夹
(2)在node_modules 中,根据包名,找对应的vue文件夹
(3)在vue文件夹中,找一个叫做package.json的包配置文件
(4)在package.json文件中,查找一个main属性【main属性指定了这个包在被加载的时候 的入口文件】
因为在Vue包的package.json文件中main属性指定的入口文件【"main": "dist/vue.runtime.common.js",】,因此,在main.js中使用import Vue from 'vue' 导入的Vue构造函数,功能不完善。
解决办法:
(1)import Vue from '../node_modules/vue/dist/vue.js'
(2)在Vue包的package.json文件中main属性指定的入口文件修改为【"main": "dist/vue.js",】
(3)在项目的webpack.config.js中添加resolve属性
1. resolve: {
2. alias: {
3. // 修改Vue倍导入时包的路径
4. "vue$" : "vue/dist/vue.js"
5. }
6.
https://blog.csdn.net/sleepwalker_1992/article/details/82082400
vant 编译有问题 内部引用vue runtime
import aLiCallPlugin from "./aLiCall";
import tianRunCallPlugin from "./tianRunCall";
const version = "1.0.0";
const components = [aLiCallPlugin, tianRunCallPlugin];
const install = Vue => {
const localVue = Vue;
if (install.installed) return;
components.forEach(component => {
localVue.component(component.name, component);
});
localVue.prototype.$aLiCallPlugin = aLiCallPlugin;
localVue.prototype.$tianRunCall = tianRunCallPlugin;
};
// 判断是否是直接引入文件
if (typeof window !== "undefined" && window.Vue) {
install(window.Vue);
}
export { version, install, aLiCallPlugin, tianRunCallPlugin };
rollup 不支持 css scoped
const _withId = /*#__PURE__*/vue$1.withScopeId("data-v-88776a9e");
vant源码有报错
组件中尽量用vue 运行时 即使用 vue.common.runtime.js
https://stackoverflow.com/questions/53773128/vuejs-cannot-read-property-use-of-undefined-error
出问题的地方在 babel的core-js,这个包里面使用有一个有一个判断优先级调整一下就好
解决参考文章 https://blog.csdn.net/qq_27667337/article/details/90634305
代码地址node_modules/core-js/client/core.js
原代码
// Node.js
if (isNode) {
notify = function () {
process.nextTick(flush);
};
// browsers with MutationObserver, except iOS Safari - https://github.com/zloirock/core-js/issues/339
} else if (Observer && !(global.navigator && global.navigator.standalone)) {
var toggle = true;
var node = document.createTextNode('');
new Observer(flush).observe(node, { characterData: true }); // eslint-disable-line no-new
notify = function () {
node.data = toggle = !toggle;
};
// environments with maybe non-completely correct, but existent Promise
} else if (Promise && Promise.resolve) {
// Promise.resolve without an argument throws an error in LG WebOS 2
var promise = Promise.resolve(undefined);
notify = function () {
promise.then(flush);
};
// for other environments - macrotask based on:
// - setImmediate
// - MessageChannel
// - window.postMessag
// - onreadystatechange
// - setTimeout
} else {
notify = function () {
// strange IE + webpack dev server bug - use .call(global)
macrotask.call(global, flush);
};
}
修改后的代码
if (isNode) {
notify = function () {
process.nextTick(flush);
};
// browsers with MutationObserver, except iOS Safari - https://github.com/zloirock/core-js/issues/339
} else if (Promise && Promise.resolve) {
// Promise.resolve without an argument throws an error in LG WebOS 2
var promise = Promise.resolve(undefined);
notify = function () {
promise.then(flush);
};
// for other environments - macrotask based on:
// - setImmediate
// - MessageChannel
// - window.postMessag
// - onreadystatechange
// - setTimeout
} else if (Observer && !(global.navigator && global.navigator.standalone)) {
var toggle = true;
var node = document.createTextNode('');
new Observer(flush).observe(node, { characterData: true }); // eslint-disable-line no-new
notify = function () {
node.data = toggle = !toggle;
};
// environments with maybe non-completely correct, but existent Promise
} else {
notify = function () {
// strange IE + webpack dev server bug - use .call(global)
macrotask.call(global, flush);
};
}
结论 :vant 中bug太多
安装必要的PostCSS插件。
在项目里,会使用到四个插件 - 两个是语法糖,一个用来在兼容旧浏览器的新CSS特性,一个用来压缩,减少生成的样式文件大小。
postcss-simple-vars
— 可以使用Sass风格的变量(e.g. $myColor: #fff;
,color: $myColor;
)而不是冗长的CSS语法(e.g. :root {--myColor: #fff}
,color: var(--myColor)
)。这样更简洁;我更喜欢较短的语法。postcss-nested
— 允许使用嵌套规则。实际上我不用它写嵌套规则;我用它简化BEM友好的选择器的写法并且划分我的区块,元素和修饰到单个CSS块。postcss-cssnext
— 这个插件集使得大多数现代CSS语法(通过最新的CSS标准)可用,编译后甚至可以在不支持新特性的旧浏览器中工作。cssnano
— 压缩,减小输出CSS文件大小。相当于JavaScript中对应的UglifyJS。使用这个命令安装插件:
npm install --save-dev postcss-simple-vars postcss-nested postcss-cssnext cssnano
按需加载
vue3 及依赖有问题,原rollup-plugin-vue 插件是yyx开发,最新版会将模板编译成vue3语法,出现大量undefined情况 ,初步估计插件不完整(据官方:vue3是兼容vue2语法的)
https://github.com/skyplaying/rollup-plugin-vue2 解决编译成vue3语法问题
结论:谨慎使用ui组件库 大多数组件库依赖webpack 如antd vant 其中也有一部分bug 建议手写组件
以上仅记录开发sdk中的问题,实战开发组件库和sdk构建细节待更新~~~
vuecli 开发组件库待更新~~~
wepack开发组件库及umd待更新~~~
构建原理梳理待更新~~~