需求:构建vue组件库成为js sdk 浏览器直接运行
umd是通用格式,兼容各种环境
具体js规范可以看这篇 JS模块化总结
以下是rollup构建过程中遇到的各种问题
rollup开发依赖包(npm library),解决引入外部依赖失败的有效方法
import nodePolyfills from 'rollup-plugin-node-polyfills';plugins: [vue(),nodePolyfills(),
]
(!) Missing global variable name
出现这个问题的原因是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
- Unused external imports 这个问题是因为import了uglify但是没用,忽略
- Circular dependencies 因为历史原因,库中有使用yss-biz这个alias,后面通过rollup-plugin-includepaths重新定义这个别名的指向,最终出现循环引用,忽略
this
has been rewritten toundefined
这是因为库中写的代码不正确用了箭头函数然后还绑定了this
,忽略- Unused external imports 这个是因为导入的内容没有使用,忽略
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位置尽量在上面,作者本人的插件顺序如下
import path from 'path';
import babel from 'rollup-plugin-babel';
import nodeResolve from 'rollup-plugin-node-resolve';
import { terser } from 'rollup-plugin-terser';
import vue from 'rollup-plugin-vue2';
// import vue from 'rollup-plugin-vue';
import postcss from 'rollup-plugin-postcss';
import json from 'rollup-plugin-json';
import replace from 'rollup-plugin-replace';
import nodePolyfills from 'rollup-plugin-node-polyfills';
import builtins from 'rollup-plugin-node-builtins';
import globals from 'rollup-plugin-node-globals';
import commonjs from '@rollup/plugin-commonjs';
import alias from '@rollup/plugin-alias';import css from 'rollup-plugin-css-only';// PostCSS plugins
// import nested from 'postcss-nested';
// import simpleVars from 'postcss-simple-vars';
// import cssnext from 'postcss-cssnext';
// import cssnano from 'cssnano';
import esbuild from 'rollup-plugin-esbuild'; // plugin-esbuild将ts变为jsconst env = process.env.NODE_ENV;
const resolveFile = function(filePath) {return path.join(__dirname, '..', filePath);
};
// const Global = `var Vue__default =_interopDefaultLegacy(Vue)`;
// 插件
const plugins = [vue({css: true,compileTemplate: true,include: /\.vue$/,target: 'browser',}),// css(),nodeResolve({preferBuiltins: true,browser: true,jsnext: true,main: true,}),commonjs(),nodePolyfills(),globals(),replace({'process.env.NODE_ENV': JSON.stringify(env),'process.env.NODE_DEBUG': JSON.stringify(process.env.NODE_DEBUG),}),postcss({modules: false,extensions: ['.less', '.css', '.scss'],// plugins: [nested(), simpleVars(), cssnext({ warnForDuplicates: false }), cssnano()],}),builtins(),json(),babel({exclude: 'node_modules/**',runtimeHelpers: true,}),
];
export default [// 多出口入口{input: './src/packages/index.js',// external: ['vue'], // 不打包output: [{file: './example/h5/dist/cloudCall.umd.js',name: 'cloudCall',format: 'umd', // 支持amd和common.js规范window.Vuesourcemap: true, // es->es6globals: {vue: 'Vue',jquery: '$',axios: 'axios',},},],plugins: [...plugins,// terser()],},
];
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@3yarn 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
Vue.observable小型状态管理
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
本地开启https服务 ===> https://codecat.blog.csdn.net/article/details/113634604
安装最新版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-rollupnpm 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,编译的时候 consoleuseBuiltIns: '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 };
下部分Css模块配置暂未更新,可以做到支持
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.jsif (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-newnotify = 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 2var 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 2var 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-newnotify = 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);};}
安装必要的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
按需加载
rollup-plugin-vue 插件最新版会将模板编译成vue3源码语法,出现大量undefined情况 ,初步估计插件不完整(据官方:vue3是兼容vue2语法的)
使用rollup-plugin-vue2 解决vue2 rollup编译问题
结论:使用ui组件库 等第三方组件库 需要熟悉源码避免选择无法编译完整的框架 element可以直接编译成功 (因为其组件写法遵循import方式引入,vant,antd-vue稍微不一样)
以上仅记录开发sdk中的问题,实战开发组件库和sdk构建细节待更新~~~
vue cli 开发组件库待更新~~~
wepack开发组件库及umd待更新~~~
构建原理梳理待更新~~~