从 0 到 1 创建一个自己的组件
什么是Rollup
Rollup 是一个 JavaScript 模块打包器,可以将小块代码编译成大块复杂的代码,例如 library 或应用程序。Rollup 对代码模块使用新的标准化格式,这些标准都包含在 JavaScript 的 ES6 版本中,而不是以前的特殊解决方案,如 CommonJS 和 AMD。ES6 模块可以使你自由、无缝地使用你最喜爱的 library 中那些最有用独立函数,而你的项目不必携带其他未使用的代码。ES6 模块最终还是要由浏览器原生实现,但当前 Rollup 可以使你提前体验。
rollup安装与使用
安装
yarn add rollup -g // 全局安装
yarn add rollup -D // 项目本地安装
创建一个项目
- 新建文件夹,初始化文件夹
yarn init -y
- 安装
rollup
yarn add rollup -D
- 新建一个文件夹
src,src下创建两个js文件:index.js,hello.jsindex.js
import hello from "./hello"; hello()hello.js
export default function hello(){ console.log('hello'); } - 运行打包
- 如果是全局安装
rollup -i src/index.js -o dist/bundle.js -f es- 如果是本地安装,在
package.json的script字段中添加: 然后执行yarn dev
"dev": "rollup -i src/index.js -o dist/bundle.js -f es" - 得到的运行结果
rollup -i src/index.js -o dist/bundle.js -f es这段指令中-i=> 打包的文件-i是--input的缩写src/index.js=> 是指入口文件-o=> 输出的文件,-o是--output.file或者--file的缩写(没有这个参数,默认输出到控制台)dist/bundle.js=> 输出文件-f=> 打包文件的格式,-f是--format的缩写。es是-f的参数,表示打包文件使用ES6模块规范。rollup支持的打包文件的格式有amd, cjs, es\esm, iife, umd。其中,amd为AMD标准,cjs为CommonJS标准,esm\es为ES模块标准,iife为立即调用函数,umd同时支持amd、cjs和iife。
rollup 配置
和webpack一样,rollup一样有配置文件去简化打包命令,同时还能更加科学的使用rollup
- 在根目录下创建
rollup.config.js
export default {
input: "./src/index.js",
output: [{
file: './dist/my-temp-umd.js',
format: 'umd',
name: 'myTemp'
//当入口文件有export时,'umd'格式必须指定name
//这样,在通过<script>标签引入时,才能通过name访问到export的内容。
},
{
file: './dist/my-temp-es.js',
format: 'es'
},
{
file: './dist/my-temp-cjs.js',
format: 'cjs'
}
]
}
- 使用
rollup配置文件可以使用rollup --config或者rollup -c。
//修改package.json的script字段
"dev": "rollup -c" // 默认使用rollup.config.js
"dev": "rollup -c rollup.dev.config.js" //使用自定义的配置文件,rollup.dev.config.js,可以配置两套不同的打包配置,用以区分开发和生产环境
src/index.js
import hello from './hello'
hello()
export const world = 'world'
- 打包后的文件
rollup插件及其使用
以上仅仅是
rollup的基本使用,在实际的使用环境下我们需要像webpack一样,对代码、依赖以及文件进行一系列处理,以及代码性能优化。
rollup-plugin-babel
rollup-plugin-babel用于转换es6语法。
将src/hello.js中的内容改写成:
export const hello = () => {
console.log('hello world')
}
箭头函数未转换
使用插件,安装yarn add rollup-plugin-babel @babel/core @babel/preset-env -D
//rollup.config.js
import babel from 'rollup-plugin-babel'
export default {
input: ...,
output: ...,
plugins:[
babel({
exclude: 'node_modules/**'
})
]
}
在根目录创建.babelrc文件
{
"presets": [
[
"@babel/preset-env"
]
]
}
重新打包
@rollup/plugin-commonjs
rollup默认是不支持CommonJS模块的,自己写的时候可以尽量避免使用CommonJS模块的语法,但有些外部库的是cjs或者umd(由webpack打包的),所以使用这些外部库就需要支持CommonJS模块。
这里模拟下这个场景
新建文件src/util.js
module.exports = { a: 1 }
在 src/index.js 中 引入
import util from './util'
console.log(util.a)
此时yarn dev 会报错
安装插件
yarn add @rollup/plugin-commonjs -D
//rollup.config.js
import commonjs from '@rollup/plugin-commonjs'
export default {
input: ...,
output: ...,
plugins:[
commonjs()
]
}
重新打包
我们还可以使用require引入模块
//src/index.js
const util = require('./util')
console.log(util.a)
rollup-plugin-postcss
处理css需要用到的插件是
rollup-plugin-postcss。它支持css文件的加载、css加前缀、css压缩、对scss/less的支持
安装
yarn add rollup-plugin-postcss -D
//rollup.config.js
import postcss from 'rollup-plugin-postcss'
export default {
input: ...,
output: ...,
plugins:[
postcss()
]
}
创建一个 css 文件在 src/index.js 引入
//src/index.js
import './css/index.css'
//css/index.css
body {
font-size: 30px;
}
重新打包
导入的css文件将用于生成style标签,插入到head中。
在根目录下我们新建一个src/index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script src="./dist/my-temp-umd.js"></script>
<div id="app">
嘿嘿
</div>
</body>
</html>
可以在网页结构中看到
该插件不能直接解析less、scss文件,在vue文件中的less、scss是可以解析的,解析vue文件的插件下文有介绍
autoprefixer
给
css3的一些属性加前缀,增加浏览器对css3的兼容
- 安装
yarn add autoprefixer@8.0.0 -D
//rollup.config.js
import postcss from 'rollup-plugin-postcss'
import autoprefixer from 'autoprefixer'
export default {
input: ...,
output: ...,
plugins:[
postcss({
plugins: [
autoprefixer()
]
})
]
}
-
配置
browserslist- 建立.browserslistrc文件
- 在package.json里面配置,在
package.json中,添加"browserslist"字段。
"browserslist": [ "defaults", "not ie < 8", "last 2 versions", "> 1%", "iOS 7", "last 3 iOS versions" ] -
修改
css内容
//src/css/index.css
body {
font-size: 30px;
display: flex;
}
- 重新打包
cssnano
除了提高对css3的兼容,我们还要对css代码进行压缩那么cssnano就是用于压缩的插件
- 安装
yarn add cssnano -D
//rollup.config.js
import cssnano from 'cssnano'
export default {
input: ...,
output: ...,
plugins:[
postcss({
plugins: [
cssnano()
]
})
]
}
- 重新打包后 [ 去除了空格和换行 ]
抽离单独的css文件
rollup-plugin-postcss可配置是否将css单独分离,默认没有extract,css样式生成style标签内联到head中,配置了extract,就会将css抽离成单独的文件。
//rollup.config.js
import postcss from 'rollup-plugin-postcss'
export default {
input: ...,
output: ...,
plugins:[
postcss({
plugins: [
autoprefixer(),
cssnano()
],
extract: 'css/index.css'
})
]
}
- 重新打包
- 在
index.html需要额外引用打包后的css文件
rollup-plugin-vue
rollup-plugin-vue用于处理.vue文件。vue2和vue3项目所用的rollup-plugin-vue版本不一样,vue的编译器也不一样。
-
vue2:
rollup-plugin-vue^5.1.9+vue-template-compileryarn add rollup-plugin-vue@5.1.9 vue-template-compiler -D -
vue3:
rollup-plugin-vue^6.0.0+@vue/compiler-sfcyarn add rollup-plugin-vue@6.0.0 @vue/compiler-sfc -D
这里以 vue2 为例子
//rollup.config.js
import vue from 'rollup-plugin-vue'
export default {
input: ...,
output: ...,
plugins:[
vue()
]
}
新建一个src/component/hello/hello.vue文件
<template>
<div class="hello">
{{ msg }}
</div>
</template>
<script>
export default {
name: "hello",
data() {
return {
msg: "我是 hello 组件",
};
},
};
</script>
<style lang="less" scoped>
.hello {
color: red;
}
</style>
//src/index.js
import './css/index.css'
import Hello from './component/hello/hello.vue';
const install = (Vue)=>{
Vue.component(Hello.name,Hello)
}
export default install
//index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link rel="stylesheet" href="./dist/css/index.css">
</head>
<body>
<div id="app">
嘿嘿
<hello></hello>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="./dist/my-temp-umd.js"></script>
</body>
<script>
Vue.use(myTemp)
new Vue({
el: '#app'
})
</script>
</html>
重新打包
rollup-plugin-vue也是默认支持scss、less、stylus,可以在项目中直接使用。给.vue文件中的css自动加前缀,需要在rollup-plugin-vue中配置。更多配置参考rollup-plugin-vue
//rollup.config.js
export default {
input: ...,
output: ...,
plugins:[
vue({
style: {
postcssPlugins: [
autoprefixer(),
cssnano()
]
}
})
]
}
rollup-plugin-terser
适用于
ES6 +的JavaScript解析器。rollup-plugin-uglify也能解析但是它只能翻译es5语法。如果要转译es6+语法,请改用terser
安装
yarn add rollup-plugin-terser -D
//rollup.config.js
import {terser} from 'rollup-plugin-terser'
export default {
input: ...,
output: ...,
plugins:[
terser()
]
}
重新打包
@rollup/plugin-alias
一般用于解析第三方依赖或者对路径的别名
安装
yarn add @rollup/plugin-alias -D
如果使用了 生产和开发环境都需要更换
//rollup.config.js
import alias from '@rollup/plugin-alias';
export default {
input: ...,
output: ...,
plugins:[
alias({
entries: [{
find: '@',
replacement: resolveDir('src')
}]
})
]
}
修改文件引入
//src/index.js
import '@/css/index.css'
import Hello from '@/component/hello/hello.vue';
const install = (Vue)=>{
Vue.component(Hello.name,Hello)
}
export default install
rollup-plugin-serve、rollup-plugin-livereload
rollup-plugin-serve用于启动一个服务器,rollup-plugin-livereload用于文件变化时,实时刷新页面。
安装
yarn add rollup-plugin-livereload rollup-plugin-serve -D
//rollup.config.js
import serve from 'rollup-plugin-serve'
import livereload from 'rollup-plugin-livereload'
export default {
...
plugins:[
serve({
contentBase: '', //服务器启动的文件夹,默认是项目根目录,需要在该文件下创建index.html
port: 8020 //端口号,默认10001
}),
livereload('dist') //watch dist目录,当目录中的文件发生变化时,刷新页面
]
}
我们在index.html的文件手动引入已经打包好的js、css文件。此时修改src中的文件,页面并不会实时刷新,因为dist目录下的文件并没有更新。 rollup监听源文件的改动很简单,就是在执行打包命令时,添加 -w 或者 --watch
//package.json
"scripts": {
"dev": "rollup -wc"
}
实现按需加载的组件
- 新建
src/component/hello/index.js,新建src/component/test/index.js和src/component/test/test.vue
//src/component/hello/index.js
import Hello from '@/component/hello/hello.vue';
export default (Vue) => {
Vue.component(Hello.name, Hello)
}
//src/component/test/index.js
import Test from '@/component/test/test.vue';
export default (Vue) => {
Vue.component(Test.name, Test)
}
//src/component/test/test.vue
<template>
<div class="test">
{{ msg }}
</div>
</template>
<script>
export default {
name: "test",
data() {
return {
msg: "我是 test 组件",
};
},
};
</script>
<style lang="less" scoped>
.test {
color: blue;
}
</style>
//src.index.js
import '@/css/index.css'
import Hello from '@/component/hello';
import Test from '@/component/test';
const install = (Vue) => {
Vue.use(Hello)
Vue.use(Test)
}
export default install
export {
Hello,
Test
}
打包后修改package.json
"main": "./dist/my-lib-cjs.js",
"module": "./dist/my-lib-es.js",
本地调试组件
- 将刚刚开发完的组件库
copy到我们新建的vue项目的node_modules文件目录下 在文件夹里面运行npm link - 在项目的
package.json修改
"devDependencies": {
"@babel/core": "^7.12.16",
"@babel/eslint-parser": "^7.12.16",
"@vue/cli-plugin-babel": "~5.0.0",
"@vue/cli-plugin-eslint": "~5.0.0",
"@vue/cli-service": "~5.0.0",
"eslint": "^7.32.0",
"eslint-plugin-vue": "^8.0.3",
"vue-template-compiler": "^2.6.14",
"my-temp": "^1.0.0" //这个名称就是 我们组件库的`package.json`文件的 name
},
main.js
import {Hello,Test} from "my-temp";
import MyTemp from "my-temp";
// console.log(Hello);
// console.log(Test);
console.log(MyTemp);
Vue.use(Hello)
Vue.use(Test)
Vue.use(MyTemp)
app.vue
<template>
<div id="app">
<!-- <img alt="Vue logo" src="./assets/logo.png" />
<HelloWorld msg="Welcome to Your Vue.js App" /> -->
<hello></hello>
<test></test>
</div>
</template>
<script>
// import HelloWorld from "./components/HelloWorld.vue";
export default {
name: "App",
components: {
// HelloWorld,
},
};
</script>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>
-启动项目