关于rollup:rollup简易使用

参考原链接:https://juejin.cn/post/693469...作者:Alaso起源:稀土掘金 rollup装置与应用装置npm i rollup -g # 全局装置npm i rollup -D # 我的项目本地装置应用不应用配置文件配置到script中 "build": "rollup -i src/index.js -o dist/bundle.js -f es"参数解释 -i指定要打包的文件,-i是--input的缩写。src/index.js是-i的参数,即打包入口文件。-o指定输入的文件,是--output.file或--file的缩写。(如果没有这个参数,则间接输入到控制台)dist/bundle.js是-o的参数,即输入文件。-f指定打包文件的格局,-f是--format的缩写。es是-f的参数,示意打包文件应用ES6模块标准。 npm run build应用配置文件在我的项目根目录下创立rollup.config.js export default {input: "./src/index.js",output: [ { file: './dist/my-lib-umd.js', format: 'umd', name: 'myLib' //当入口文件有export时,'umd'格局必须指定name //这样,在通过<script>标签引入时,能力通过name拜访到export的内容。 }, { file: './dist/my-lib-es.js', format: 'es' }, { file: './dist/my-lib-cjs.js', format: 'cjs' }]}应用Rollup的配置文件,能够应用rollup --config或者rollup -c指令。//批改package.json的script字段 "dev": "rollup -c" // 默认应用rollup.config.js"dev": "rollup -c my.config.js" //应用自定义的配置文件,my.config.js解决js容许第三方模块rollup-plugin-node-resolve 该插件会容许加载在 node_modules中的第三方模块。 依赖装置npm i rollup-plugin-node-resolve配置插件import resolve from 'rollup-plugin-node-resolve';export default { input: ..., output: ..., plugins:[ resolve() ]}根目录创立.babelrc文件配置 ...

October 17, 2022 · 2 min · jiezi

关于rollup:rollup打包出现Unresolved-dependencies

目前code-js版本3.24.1 , node_modules中的确有core-js这个包该怎么解决上图的异样

August 17, 2022 · 1 min · jiezi

关于rollup:Rollup打包

rollup简洁,小,高效。默认开启treeshaking,输入后果更加扁平,打包后果齐全可读,加载非ESM的第三方模块比较复杂,模块最终都被打包到一个函数中,无奈实现HMR,浏览器环境中,代码拆分性能依赖AMD库,实用于开发一个框架或者类库,很少在代码中依赖第三方模块能够通过命令行形式进行简略的打包如 yarn rollup ./src/index.js --format iife --file dist/index.js也能够通过配置文件形式进行配置,不过运行时须要加--config参数,因为默认不会打包不会应用配置文件配置文件如 export default { input: 'src/index.js', output: { file: 'dist/bundle.js', format: 'iife' }}运行命令 yarn rollup --config yarn rollup --config rollup.config.js // 或者prod.config.js等等指定配置文件名应用插件插件是Rollup惟一扩大形式 import json from 'rollup-plugin-json' // 一个导入json文件插件export default { input: 'src/index.js', output: { file: 'dist/bundle.js', format: 'iife' }, plugins: [ json() // 调用后果放入plugins数组中 ]}应用NPM模块能够借助rollup-plugin-node-resolve插件,放入plugins中 import resolve from 'rollup-plugin-node-resolve'... plugins: [ json(), resolve() ]...加载CommonJS模块默认不被反对,因为rollup就是为了打包ESM模块.须要借助rollup-plugin-commonjs import commonjs from 'rollup-plugin-commonjs'... plugins: [ json(), resolve(), commonjs() ]...代码拆分应用动静导入实现代码拆分 ...

January 30, 2022 · 1 min · jiezi

关于rollup:打包工具Rollup

与 webpack 作用相似,Rollup 更为玲珑,它仅仅是一款 ESM 打包器,并没有其余额定性能,例如自动化的插件,HMR 等在 Rollup 中不反对 装置 yarn add rollup --dev执行打包命令 file:打包输入的文件目录format:指定打包输入的格局yarn rollup ./src/index.js --file dist/bundle.js --format iife查看打包后果 (function () { "use strict"; const log = (msg) => { console.log("---------- INFO ----------"); console.log(msg); console.log("--------------------------"); }; var messages = { hi: "Hi~", }; // 导入模块成员 // 应用模块成员 const msg = messages.hi; log(msg);})();代码相比 webpack 大量疏导代码和模块函数,这里的输入很简略清晰,没有多余代码,输入代码中只会保留用到的局部,对于未援用的局部都没有输入,这是因为 rollup 默认会主动开启 tree shaking 配置文件在我的项目中创立一个名为 rollup.config.js 的文件,减少如下代码: export default { input: "src/index.js", output: { file: "dist/bundle.js", format: "iife", },};执行打包命令 ...

December 1, 2021 · 2 min · jiezi

关于rollup:Rollup个人笔记

Rollup与webpack作用相似,Rollup更为玲珑,它仅仅是一款ESM打包器,并没有其余额定性能, 例如自动化的插件,HMR等在Rollup中不反对 它的诞生并不是要与webpack全民竞争,只是提供一个充分利用ESM各项个性的高效打包器 装置: yarn add rollup --dev(^1.26.3) 应用:yarn rollup ./src/index.js入口文件 --format iife --file dist/bundle.js输入文件 查看rollup命令yarn rollup # index.js 根文件// 导入模块成员import { log } from './logger'import messages from './messages'// 应用模块成员const msg = messages.hilog(msg)应用打包命令后,会生成 dist/bundle.js 文件 代码相比webpack大量疏导代码和模块函数,这里的输入很简略清晰,没有多余代码 输入代码中只会保留用到的局部,对于未援用的局部都没有输入,这是因为rollup默认会主动开启tree shaking,树摇最早在rollup中提出 # bundle.js(function () { 'use strict'; const log = msg => { console.log('---------- INFO ----------'); console.log(msg); console.log('--------------------------'); }; var messages = { hi: 'Hey Guys, I am zce~' }; // 导入模块成员 // 应用模块成员 const msg = messages.hi; log(msg);}());配置文件rollup.config.js运行在node环境中,rollup会额定解决这个文件,因而也容许应用ESM ...

June 5, 2021 · 2 min · jiezi

关于rollup:入门rollup

overview以一个最根本的demo展现rollup的性能/用法。 init projectmkdir exRollupcd exRollupnpm initnpm i -d rollupnpm i -d rollup-plugin-json编辑package.json{ ... "scripts": { ... "build:cjs": "rollup -c ./config/rollup.config.cjs.js", "build:esm": "rollup -c ./config/rollup.config.esm.js", "build:iife": "rollup -c ./config/rollup.config.iife.js", "build:umd": "rollup -c ./config/rollup.config.umd.js", "build": "npm run build.cjs & npm run build:esm & npm run build:iife & npm run build:cmd" }}编辑配置文件本示例中有4个配置文件。别离用于生成commonjs标准代码/esm标准代码/立刻执行代码/umd标准代码。 // rollup.config.cjs.jsimport json from 'rollup-plugin-json';export default { input: 'src/index.js', output: { file: 'dist/bundle.cjs.js', format: 'cjs' }, plugins: [ json() ]};// rollup.config.esm.jsimport json from 'rollup-plugin-json';export default { input: 'src/index.js', output: { file: 'dist/bundle.esm.js', format: 'esm' }, plugins: [ json() ]};// rollup.config.iife.jsimport json from 'rollup-plugin-json';export default { input: 'src/index.js', output: { file: 'dist/bundle.iife.js', format: 'iife' }, plugins: [ json() ]};// rollup.config.umd.jsimport json from 'rollup-plugin-json';export default { input: 'src/index.js', output: { file: 'dist/bundle.umd.js', format: 'umd' }, plugins: [ json() ]};编辑代码// src/foo.jsexport default function (a, b) { return a + b}// src/index.jsimport {version} from '../package.json'import add from './foo.js'export default function () { console.log(`version: ${version}`)}export let sum = function (a, b) { return add(a, b)}执行打包npm run build

May 14, 2021 · 1 min · jiezi

关于rollup:为什么说rollup比webpack更适合打包库

前言大略一年前写了个小小的js插件 remember-scroll,并且分享了一篇文章:用Class写一个记住用户来到地位的js插件,是一个纯js库,性能是在用户再次进入页面时能主动定位到上一次浏览的地位,应用webpack+babel打包,外面的webpack和babel的配置至今看来也算是很典型的。 前端打包工具有很多——webpack,gulp,rollup等等,网上有很多文章剖析它们别离更适宜哪些场景,webpack更适宜打包组件库、应用程序之类的利用,而rollup更适宜打包纯js的类库。因而笔者始终有想法尝试将 remember-scroll 的打包工具由webpack更换为rollup,从理论利用的角度来比照一下两者的区别。 从零配置rollup装置rollup和一些插件npm i rollup rollup-plugin-uglify rollup-plugin-filesize @rollup/plugin-node-resolve @rollup/plugin-commonjs -Drollup-plugin-uglify 用于压缩混同打包后的js。rollup-plugin-filesize打包后在控制台显示文件大小。@rollup/plugin-node-resolve让 rollup 可能辨认node_modules的第三方模块。@rollup/plugin-commonjs将 CommonJS 的模块转换为 ES2015 供 rollup 解决。增加babelnpm i @rollup/plugin-babel @babel/core @babel/plugin-transform-runtime @babel/preset-env core-js@2 -D@rollup/plugin-babel rollup 的babel插件。@babel/core babel外围。@babel/plugin-transform-runtime 用于防止净化全局函数(不是必须要用到,但作为类库最好要加上)。@babel/preset-env 主动依据指标浏览器注入相干的polyfill。core-js polyfill的类库,这里应用的是2.x版本(应用3会减少包的大小)。根目录下的babel.config.js如下: const presets = [ [ '@babel/env', { useBuiltIns: 'usage', corejs: { version: 2 } }, ],]const plugins = [ '@babel/plugin-transform-runtime']module.exports = { presets, plugins }根目录下新建rollup.config.js,全副配置如下:import filesize from 'rollup-plugin-filesize'import babel from '@rollup/plugin-babel'import resolve from '@rollup/plugin-node-resolve'import { uglify } from 'rollup-plugin-uglify'import commonjs from '@rollup/plugin-commonjs'const isProd = process.env.NODE_ENV === 'production'export default { input: 'src/index.js', output: { file: isProd ? 'dist/remember-scroll.min.js' : 'dist/remember-scroll.js', format: 'umd', exports: 'default', name: 'RememberScroll', }, plugins: [ resolve(), commonjs(), filesize(), babel({ babelHelpers: 'runtime', exclude: ['node_modules/**'] }), (isProd && uglify()) ]}package.json打包命令如下: "build": "rollup -c --environment NODE_ENV:production && rollup -c", "dev": "rollup -c --watch",总之,所有配置都是与之前webpack版本的一样,都应用了babel。npm run build就能够将资源打包到dist了,接下来咱们比照一下webpack和rollup两个工具打进去的体积有啥区别。 ...

December 29, 2020 · 1 min · jiezi

从0搭建rollupvue组件模板轻松发布npmgithubpages

前言既然是rollup+vue组件模板,就不说明为什么采用这个模式来开发组件了。需要了解rollup的看文档:rollup官方文档 rollup打包找个文件夹,开干 mkdir vue-rollup-component-templatecd vue-rollup-component-templatenpm init安装 rollup npm i -D rollup配置文件 rollup.config.js export default { input: 'src/index.js', output: { name: 'vue-rollup-component-template', file: 'dist/vue-rollup-component-template.js', format: 'umd' }}入口文件 src/index.js const x = 1;export default (y) => x + y修改 package.json 命令 "scripts": { "build": "rollup --config rollup.config.js"}打包 npm run build完成了一个简单的打包。 不同打包格式与命令 "scripts": { "build": "npm run build:browser && npm run build:es && npm run build:umd", "build:browser": "rollup --config build/rollup.config.browser.js", "build:es": "rollup --config build/rollup.config.es.js", "build:umd": "rollup --config build/rollup.config.umd.js"},通用配置 build/rollup.config.base.js ...

July 12, 2019 · 3 min · jiezi

VUE2610scriptsconfigjs

rollup -w -c scripts/config.js --environment TARGET:web-full-dev-c 指定配置文件-w 监听文件,文件发生改变时重新构建--environment 设置环境变量。如rollup -c --environment TARGET:web-full-dev 可以通过process.env.TARGET获取 if (process.env.TARGET) { // 根据TARGET生成rollup config对象 module.exports = genConfig(process.env.TARGET) //生成rollup config对象} else { //如果没有设置TARGET,返回生成函数 exports.getBuild = genConfig exports.getAllBuilds = () => Object.keys(builds).map(genConfig)}rollup -w -c scripts/config.js --environment TARGET:web-full-dev 对应rollup config对象如下: { input: opts.entry, //入口 src/platforms/web/entry-runtime-with-compiler.js external: opts.external, plugins: [ flow(), alias(Object.assign({}, aliases, { he: './entity-decoder' })) ].concat(opts.plugins || []), output: { file: resolve('dist/vue.js'), format: 'umd', // umd – 通用模块定义,以amd,cjs 和 iife 为一体 banner: opts.banner, name: opts.moduleName || 'Vue' }, onwarn: (msg, warn) => { //拦截警告信息 if (!/Circular/.test(msg)) { warn(msg) } }}rollup-plugin-flow-no-whitespace //去除flow静态类型检查代码rollup-plugin-alias //为模块提供别名rollup-plugin-buble //编译ES6+语法为ES2015,无需配置,比babel更轻量rollup-plugin-replace //替换代码中的变量为指定值参考资料:1、rollup文档 ...

June 4, 2019 · 1 min · jiezi

gulp-gulpbetterrollup-rollup-构建-ES6-开发环境

gulp + gulp-better-rollup + rollup 构建 ES6 开发环境关于 Gulp 就不过多啰嗦了。常用的 js 模块打包工具主要有 webpack、rollup 和 browserify 三个,Gulp 构建 ES6 开发环境通常需要借助这三者之一来合并打包 ES6 模块代码。因此,Gulp 构建 ES6 开发环境的方案有很多,例如:webpack-stream、rollup-stream 、browserify等,本文讲述使用 gulp-better-rollup 的构建过程。gulp-better-rollup 可以将 rollup 更深入地集成到Gulps管道链中。 GitHub地址:https://github.com/JofunLiang/gulp-translation-es6-demo 构建基础的 ES6 语法转译环境首先,安装 gulp 工具,命令如下: $ npm install --save-dev gulp安装 gulp-better-rollup 插件,由于 gulp-better-rollup 需要 rollup 作为依赖,因此,还要安装 rollup 模块和 rollup-plugin-babel(rollup 和 babel 之间的无缝集成插件): $ npm install --save-dev gulp-better-rollup rollup rollup-plugin-babel安装 babel 核心插件: $ npm install --save-dev @babel/core @babel/preset-env安装完成后,配置 .babelrc 文件和 gulpfile.js文件,将这两个文件放在项目根目录下。 ...

April 29, 2019 · 2 min · jiezi

Vue源码解读前必须要知道的Vue构建流程

了解Vue的构建,可以从package.json文件开始sprits命令内关于构建的命令如下{ … “build”: “node scripts/build.js”, // web版本 // sever “build:ssr”: “npm run build – web-runtime-cjs,web-server-renderer”, // weex “build:weex”: “npm run build – weex” …}从命令看出:vue是通过rollup来进行构建的同样的构建工具webpack更强大一些,可以处理图片、 css、js等;但是rollup只做js的处理,相比之下更轻量, 所以rollup更适合js框架的打包总共有三个版本的构建从web版本的为起点来了解,Web版本的构建命令实际执行的是scripts/build.js build文件的整个核心内容是build方法et builds = require(’./config’).getAllBuilds()if (process.argv[2]) { const filters = process.argv[2].split(’,’) builds = builds.filter(b => { return filters.some(f => b.output.file.indexOf(f) > -1 || b._name.indexOf(f) > -1) })} else { //. 如果没有参数就把weex给过滤掉 builds = builds.filter(b => { return b.output.file.indexOf(‘weex’) === -1 })}build(builds)得到的整个的构建流程是:读取./config 配置文件中的配置,再根据命令行中输入的参数,exports.getAllBuilds = () => Object.keys(builds).map(genConfig)// Object.keys(builds) 对象key的数组: 对应val的是不同版本的编译配置// genConfig 配置rollup构建的参数格式其中getAllBuilds方法返回的是一个对象数组去到这些配置中进行过滤,拿到对应的版本编译所需要的config, 传入到buildEntry方法去执行rollup编译rollup在.then内执行输出的文件地址,以及代码压缩配置其中config里的format 构建格式最后config文件最后导出的是遵循rollup构建规则的所需要的数组对象其中的别名配置暂不做分析,具体代码在scripts/alias中, ...

March 31, 2019 · 1 min · jiezi

Rollup使用记录

rollup也是一款打包工具,比webpack要轻量许多,用于弥补gulp的无tree-shaking是很好的选择,最大的用途是打包生产一个库文件,比如sdk.js之类。虽然webpack也可以做到,但是webpack较重,打包后的文件有部分webpack内部代码,如__webpack__require之类的函数定义,给人一种不干净的感觉。而rollup打出来的包就很干净,没有其他冗余代码。鲸鱼 注我用它打包过:单个d3图形包使用方式通过插件导入commonjs模块需要两个插件共用rollup-plugin-commonjs rollup-plugin-node-resolve// rollup.config.jsimport commonjs from ‘rollup-plugin-commonjs’;import nodeResolve from ‘rollup-plugin-node-resolve’;export default { input: ‘main.js’, output: { file: ‘bundle.js’, format: ‘iife’ }, plugins: [ nodeResolve({ jsnext: true, main: true }), commonjs({ // non-CommonJS modules will be ignored, but you can also // specifically include/exclude files include: ’node_modules/’, // Default: undefined exclude: [ ’node_modules/foo/’, ’node_modules/bar/**’ ], // Default: undefined // these values can also be regular expressions // include: /node_modules/ // search for files other than .js files (must already // be transpiled by a previous plugin!) extensions: [ ‘.js’, ‘.coffee’ ], // Default: [ ‘.js’ ] // if true then uses of global won’t be dealt with by this plugin ignoreGlobal: false, // Default: false // if false then skip sourceMap generation for CommonJS modules sourceMap: false, // Default: true // explicitly specify unresolvable named exports // (see below for more details) namedExports: { ‘./module.js’: [‘foo’, ‘bar’ ] }, // Default: undefined // sometimes you have to leave require statements // unconverted. Pass an array containing the IDs // or a id =&gt; boolean function. Only use this // option if you know what you’re doing! ignore: [ ‘conditional-runtime-dependency’ ] }) ]};现实项目示例可以戳 vue源码这里然后在配置的plugins里面使用 参考Rollup常用配置rollup.js 文档 ...

March 19, 2019 · 1 min · jiezi

【手牵手】搭建前端组件库(一)

手牵手搭建前端组件库本文梳理如何搭建和构建前端组件库.了解几个问题为何需要组件化?大部分项目起源都是源于业务方的各种各样的奇葩需求。随着公司的业务发展,公司内部开始衍生出很多的B2C系统、后台系统,前端部门也疲于应对越来越多同质化的项目,这些项目在很多基础模块层、源代码存在不小的相似,甚至存在相似的业务模块。笔者曾经所在的一个电商团队,前端成员基本每个人多做过登录注册、购物车、支付、微信登录…… 大量重复的业务代码。由于组内技术没有强制规范本质上相同的东西,重复的去code就显得浪费.分析这些问题发现:日渐增多的业务场景需求前端资源有限,无法支持所有项目的快速迭代公司内部诸多产品业务混乱、体验不统一于是开发底层的工具去服务不同业务就很有必要:设计一套公司内部的基础组件库支撑各个前端项目,提升项目和业务的可用性和一致性。一个前端团队拥有大量的业务场景和业务代码,相似的页面和代码层出不穷,如何管理和抽象这些相似的代码和模块,绝大多数团队会遇到这样的问题。 不断的拷代码? 修改代码?还是抽象成组件?显然后者更高效。所以在多项目存在高度的可控、底层依赖的情况下,前端实现组件库是最好的选择。组件化,又或者组件抽离的目的是为了功能共享方便维护,其能够带来的好处是少写代码,统一管理、统一维护。一套基础组件代码千锤百炼精而又精,从而起到快速支撑业务迭代,提升开发效率的目的。业务型组件库前端组件库百花齐放,antd、element ui这些基础组件库已经很强大,使用于各种业务场景。但是这些基础组件的粒度是基于单个交互,而在交互与产品之间隔着各种各样的模块和业务场景,产品的汇聚源于各种基础组件在业务逻辑的沾粘下集成为一个个项目,一个团队或多或少会有项目或模块存在功能、交互流程的重复、本质上的同质化。所以antd、element ui 这类组件库是基于单个非连续性的交互组件,一个组件代表着一次人机无副作用的操作与响应,其不思考实体、用户、终端的状态,最小化的暴露和响应组件内部状态。对于连续性的交互通常来说与特点的业务场景有关,存在诸多的外部依赖,目前都是在各个业务模块由用户(coder)自行编写。有没有一种方法解决连续性交互流程的共用问题?解决的办法是组件封装包含业务场景的连续性交互流程,利用组件化将内部依赖通过接口映射到外部。前端架构部门为业务部门提供业务型组件库能够有效提高开发效率.组件库设计思路组件是对一些具有相同业务场景和交互模式、交互流程代码的抽象,组件库首先应该保证各个组件的视觉风格和交互规范保持一致。组件库的 props 定义需要具备足够的可扩展性,对外提供组件内部的控制权,使组件内部完全受控。支持通过 children 自定义内部结构,预定义组件交互状态。保持组件具有统一的输入和输出,完整的API.组件库的开发我们需要考虑:组件设计思路、需要解决的场景组件代码规范组件测试组件维护,包括迭代、issue、文档、发布机制一个完整强大的组件库需要多方面努力,回归正题.使用到的基础技术vue cil 3npmwebpackrollup(v1.2.2)Demo下面就手把手搭建一个前端偏业务性的组件库。组件库包括:message 组件: 一个封装用于呈现后台通过 websocket 推送到前台页面的实时消息模块;pay 组件: 一个封装用于实现商品支付的模块share 组件: 一个封装用于实现商品、文章、视频在各社交平台分享的模块只抛出一个栗子,组件内部实现略这里注意组件抽取的粒度,组件的抽离以一个完整的连续性交互为目地。组件依赖数据、交互事件、控制权的暴露需要考虑全面,不同的上层业务部门都有自己对组件可配置的不同渴望。需要权衡,不能把配置化给捣鼓的永无止境到很难堪的局面。笔者曾经就参与一个项目的组件化,组件抽离的面目全非,各种依赖、环境、状态的配置,导致最后只有组件编写人员在看文档加回忆的情况下才能搞清楚其来龙去脉.从简单的开始1、初始化组件库目录创建一个空项目// 新建一个项目vue create qw-ui经过vue cil3初始化后的qw-ui目录:├─docs│ ├─public│├─src│ .gitignore│ babel.config.js│ package-lock.json│ package.json│ README.md│ vue.config.js│ 此时为了方便组件库的代码管理,将目录结构修改为:├─src // 用作示例 Demo│ ├─packages // 新增 packages 用于编写存放组件│├─lib // 新增 lib 用于存放编译后的输出文件│ .gitignore│ babel.config.js│ package-lock.json│ package.json│ README.md│ vue.config.js│ 目录结构可以更具需要调整.2、修改 vue.config.js 配置vue cli3 提供一个可选的 vue.config.js 配置文件。这个文件存在则他会被自动加载,所有的对项目和webpack的配置,都在这个文件中。修改 vue.config.js 配置的目的主要是:使 Demo 可访问,实现对 src目录的编译处理;提供对 package的编译、构建处理做以下两处修改:修改项目的入口entry 字段为项目入口入口修改使用 Vue CLI 3 的 page属性来配置:module.exports = { pages: { index: { // page 的入口 entry: ‘src/main.js’, // 模板来源 template: ‘public/index.html’, // 在 dist/index.html 的输出 filename: ‘index.html’ } }}添加对 packages 目录的编译处理packages 是我们后来新增的一个目录,默认是不被 webpack 处理的,所以需要通过添加配置对该目录的编译支持。新增编译处理目录,需要通过webpack的链式操作chainWebpack函数实现:module.exports = { pages: { index: { // page 的入口 entry: ’examples/main.js’, // 模板来源 template: ‘public/index.html’, // 在 dist/index.html 的输出 filename: ‘index.html’ } }, chainWebpack: config => { // packages和examples目录需要加入编译 config.module .rule(‘js’) .include.add(/packages/) .end() .include.add(/src/) .end() .use(‘babel’) .loader(‘babel-loader’) .tap(options => { // 修改它的选项… return options; }); }}执行 npm run vue-cli-service serve , 实现对Demo的访问.3、编写 packages 组件库创建一个 message组件创建组件在 packages 目录下,所有的单个组件都以文件夹的形式存储,这里创建一个目录 message 文件夹;在 message/ 目录下创建 src/ 目录存储组件源码,所有 message 依赖的除第三方资源都存放与该目录下;在 /message目录下创建 index.js` 文件对外提供对组件的引用示例代码:message/index.js 对外提供应用// message/index.jsimport message from ‘./src/message ‘message .install = function (Vue) { Vue.component(message .name, message )}export default message // message/src/message .js<template> <div class=“message”> <el-row class=“message-test”> <el-col :span=“12” class=“message-row”><p class=“text”>hello {{ message }}</p></el-col> <el-col :span=“6”> <img src="./st.png"/> </el-col> </el-row> </div></template><script>import ‘./index.scss’export default { name: ‘v-message’, // 申明组件的 name属性 props: { message: String }}</script>需要注意的是,组件 mesage 必须声明 name 属性,这个 name 就是组件的标签,如:<v-message><v-message/>packages/message目录结构如下:packages/message ├─index.js │ ├─src │ message.vue │ st.png // 组件依赖的图片 │ index.scss // 组件依赖的样式文件导出 packages 组件库修改 /packages/index.js 文件,整合所有组件,并对整个组件库进行导出:// 导入组件import hello from ‘./hello’// 存储组件列表const components = [ hello]// 定义 install 方法,接收 Vue 作为参数。如果使用 use 注册插件,则所有的组件都将被注册const install = function (Vue) { // 判断是否安装 if (install.installed) return // 遍历注册全局组件 components.map(component => Vue.component(component.name, component))}// 判断是否是直接引入文件if (typeof window !== ‘undefined’ && window.Vue) { install(window.Vue)}export default { // 导出的对象必须具有 install,才能被 Vue.use() 方法安装 install, // 以下是具体的组件列表 hello}到此,构建组件库的环境准好好了### 4、发布组件库到 npmpackages 目录的编译打包在 package.json的 scripts 字段中新增一下命令:“lib”: “vue-cli-service build –target lib –name kui –dest lib packages/index.js"vue cil3 提供了 库模式 来打包第三方库的开发,packages 的编译打包需要使用库模式–target: 构建目标,默认为应用模式。这里修改为 lib 启用库模式。–dest : 输出目录,默认 dist。这里我们改成 lib[entry]: 最后一个参数为入口文件,默认为 src/App.vue。这里我们指定编译 packages/ 组件库目录。在 vue cil3 库模式中,Vue 是外置的。这意味着包中不会有 Vue,即便你在代码中导入了 Vue。如果这个库会通过一个打包器使用,它将尝试通过打包器以依赖的方式加载 Vue;否则就会回退到一个全局的 Vue 变量。配置好了后,执行编译命令:npm run lib稍后控制台输出,即编译完成: DONE Compiled successfully in 5988ms16:05:35 File Size Gzipped lib\kui.umd.min.js 8.08 KiB 4.55 KiB lib\kui.umd.js 17.78 KiB 7.31 KiB lib\kui.common.js 17.41 KiB 7.19 KiB lib\kui.css 0.10 KiB 0.10 KiB Images and other types of assets omitted. Total task duration: 8.71s ```package.json 配置name: 包名,该名字是唯一的。可在 npm 官网搜索名字。version: 版本号,每次发布至 npm 需要修改版本号,不能和历史版本号相同。description: 描述。main: 入口文件,该字段需指向我们最终编译后的包文件。keyword:关键字,以空格分离希望用户最终搜索的词。author:作者private:是否私有,需要修改为 false 才能发布到 npmlicense: 开源协议参考配置:{ “name”: “qw-ui”, “version”: “0.1.0”, “private”: false, “main”: “lib/kui.umd.min.js”, “description”: “qw-ui”, “keyword”: “qw-ui”, “author”:“luojh”, “scripts”: { “serve”: “vue-cli-service serve”, “build”: “vue-cli-service build”, “lint”: “vue-cli-service lint”, “lib”: “vue-cli-service build –target lib –name kui –dest lib packages/index.js” }}添加 .npmignore 文件发布时,只有编译后的 lib 目录、package.json、README.md才需要被发布。所以通过配置.npmignore文件忽略不需要提交的目录和文件。# 忽略目录examples/packages/public/# 忽略指定文件vue.config.jsbabel.config.js*.map# 本地文件.env.local.env..local# 日志文件npm-debug.logyarn-debug.logyarn-error.log# 编辑器缓存文件.idea.vscode*.suo*.ntvs**.njsproj*.sln*.sw*发布到 npm首先需要在 npm 官网上注册一个账号,通过 npm adduser 命令创建一个账户,或者在 npm 官网注册注册完成后在本地命令行中登录:npm login执行发布命令,发布到 npmnpm publishnpm 淘宝镜像不支持 publish 命令,如果设置了淘宝镜像,publish 前需将镜像设置会 npm :npm config set registry http://registry.npmjs.orgnpm publish时,本地cmd终端需通过管理员运行### 5.使用组件库安装发布的组件库:npm i qw-ui使用组件:# 在 main.js 引入并注册import qwui from ‘qw-ui’Vue.use(qwui)# 在组件中使用<template> <v-message message=” hello 333 :: 使用kui组件库"></v-message></template><script> export default { data () { return { } } }</script>完! ...

February 26, 2019 · 3 min · jiezi

【手牵手】搭建前端组件库(二)

进阶组件库按需引入在目前,所有的组件会被打包进一个文件,组件库是一骨碌加载完所有组件,同时也会打包和加载多余的代码。对于小项目这样没有问题,但是当组件库越来越庞大、丰富,特别是像我们带业务逻辑的非js库,代码量会更大,如果不管不顾的一通加载完所有资源,后期肯定会带来业务方面的体验问题。所以首要的问题是实现源代码的按需引入,而按需引入的前提是实现源码包按独立组件分割和的拆分打包。代码分拆单个组件独立构建打包的思路就是给打包工具提供多个独立的入口,根据入口收集其所依赖的资源。一个组件入口产出一个文件webpack使用 webpack 配置多入口的方式来按模块拆分打包,每一个模块作为一个入口,与此同时产出对应的文件。webpack 的配置比较简单,不展开.实际构建 library 使用 webpack 有不小的缺点, 应为 webpack 产出后的文件中带有一层包裹代码,这种情况下在碎片化的组件库中反而会使打包体积变大,无法起到‘瘦身’的效果。如下的 webpack 包裹代码:/* 1 //*/ (function(module, webpack_exports, webpack_require) { ‘use strict’; / unused harmony export square / / harmony export (immutable) */ webpack_exports[‘a’] = cube; function square(x) { return x * x; } function cube(x) { return x * x * x; }});哪些额外的代码看着有点不那么清爽.rollup使用 rollup来打包 library,rollup相较于 webpack 在打包体积上会跟小,更加适合 .rollup 的特点:Tree Shaking: 自动移除未使用的代码, 输出更小的文件Scope Hoisting: 所有模块构建在一个函数内, 执行效率更高Config 文件支持通过 ESM 模块格式书写可以一次输出多种格式:模块规范: IIFE, AMD, CJS, UMD, ESMDevelopment 与 production 版本: .js, .min.js是驴是马拉出来溜溜全局安装 rollupnpm install –global rollup// orcnpm install –global rolluprollup 的迭代比较快,这里稍微留意一下 rollup 的版本,部分插件可能不兼容添加rollup.config.js在项目根目录下创建 rollup.config.js 文件:// rollup.config.jsexport default { input: ‘packages/index.js’, output: { file: ’lib/app.all.js’, format: ‘cjs’ }};input:构建入口format:编译打包格式file:编译后输出目录就这么简单,执行以下命令开始将装个 packages 构建构建为一个单文件rollup -c rollup.config.js添加 rollup 多文件构建Rollup 配置文件是一个标准 ES6 模块,默认到处一个对象,也可以到处一个对象用来构建多个模块// rollup.config.jsexport default [{ input: ‘packages/a.js’, output: { file: ’lib/app.a.js’, format: ‘cjs’ }},{ input: ‘packages/b.js’, output: { file: ’lib/app.b.js’, format: ‘cjs’ }}];packages 目录为组件库源码,相关模块不固定,不适宜写死。对于这个问题通过扫描目录获取所有模块,修改 rollup.config.js :// rollup.config.jsconst fs = require(‘fs-extra’);const path = require(‘path’);const packages = {};const dir = path.join(__dirname, ‘../packages’);const files = fs.readdirSync(dir);files.forEach(file => { const absolutePath = path.join(dir, file); if (isDir(absolutePath)) { packages[file] =packages/${file}/index.js; }});function createRollupConfig (file, name) { const config = { input: file, output: { file: lib/index.js : lib/${name}/index.js, format: ’es’, name: name, sourcemap: true } } return config}const buildPackages = []for (let name in packages) { const file = packages[name] buildPackages.push(createRollupConfig(file, name))}export default buildPackages;这里打包文件的格式我们使用 es,es是指ES6.这个时候开始构建会报错,因为rollup还不能识别组件库中的 vue 样板代码、语法,同时我们的组件库并不是纯粹的js library, 也需要处理业务组件内引用的样式和图片、字体等。仅仅是使用 rollup 还不能实现我们的目的,需要借助一系列 rollup 插件来完成处理vue.vue文件的编译需要使用rollup-plugin-vue2插件:npm rollup-plugin-vue2 –save-dev处理样式样式处理可以使用 rollup-plugin-css-only插件。由于不喜欢笨拙的css,习惯了scss语法,就直接使用 scss,但其配置就相对要复杂一点。scss样式处理可以使用rollup-plugin-scss插件,为了灵活的处理样式我使用Postcss图片处理html中引入的图片在组件库部署后就无法正常访问了,这里使用 rollup-plugin-url插件将内嵌的图片编译为 base64 再直接放入 js 文件中。对于组件库中有较多大尺寸的图片建议直接将图片放入图片服务器,然后通过url 引入,避免打包文件过大的问题.加入 rollup 插件后的配置:// rollup.config.jsconst fs = require(‘fs-extra’);const path = require(‘path’);import vue from ‘rollup-plugin-vue2’import postcss from ‘rollup-plugin-postcss’import postcssScss from ‘postcss-scss’import autoprefixer from ‘autoprefixer’import base64 from ‘postcss-base64’import url from ‘rollup-plugin-url’import progress from ‘rollup-plugin-progress’import filesize from ‘rollup-plugin-filesize’;function isDir(dir) { return fs.lstatSync(dir).isDirectory();}const packages = {};const dir = path.join(__dirname, ‘../packages’);const files = fs.readdirSync(dir);files.forEach(file => { const absolutePath = path.join(dir, file); if (isDir(absolutePath)) { packages[file] =packages/${file}/index.js; }});function createRollupConfig (file, name) { const config = { input: file, output: { file: lib/${name}/index.js, format: ’es’, name: name, sourcemap: true }, plugins: [ vue(), postcss({ extract: true, parser: postcssScss, plugins: [ base64({ extensions: [’.png’, ‘.jpeg’], root: ‘./packages/’, }), autoprefixer({ add: true }), ] }), url({ limit: 10 * 1024, //include: [’.svg’] }), progress(), filesize() ] } return config}const buildPackages = []for (let name in packages) { const file = packages[name] buildPackages.push(createRollupConfig(file, name))}export default buildPackages;到此可以运行 rollup -c rollup.config.js 打包,实现源代码按依赖关系和目录进行分拆打包:lib ├─message │ index.js | index.css | index.js.map ├─pay │ index.js | index.css | index.js.map ├─share │ index.js | index.css | index.js.map打包后的 packages/pay/index.js > lib/pay/index.js :// lib/pay/index.jsvar logo = “data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAYAAACtWK6eAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyNpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMDE0IDc5LjE1Njc5NywgMjAxNC8wOC8yMC0wOTo1MzowMiAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6OTk2QkI4RkE3NjE2MTFFNUE4NEU4RkIxNjQ5MTYyRDgiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6OTk2QkI4Rjk3NjE2MTFFNUE4NEU4RkIxNjQ5MTYyRDgiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIChNYWNpbnRvc2gpIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6NjU2QTEyNzk3NjkyMTFFMzkxODk4RDkwQkY4Q0U0NzYiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6NjU2QTEyN0E3NjkyMTFFMzkxODk4RDkwQkY4Q0U0NzYiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz5WHowqAAAXNElEQVR42uxda4xd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”;var message = {render: function(){var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c(‘div’,{staticClass:“message”},[_c(’el-row’,{staticClass:“message-test”},[_c(’el-col’,{staticClass:“message-row”,attrs:{“span”:12}},[_c(‘p’,{staticClass:“text”},[_vm._v(“message “+_vm._s(_vm.message)+” – “+_vm._s(_vm.count))])]),_vm._v(” “),_c(’el-col’,{attrs:{“span”:6}},[_c(‘p’,[_vm._v("\n css backgroud image base64\n “)]),_vm._v(” “),_c(‘div’,{staticClass:“tops”}),_vm._v(” “),_c(‘hr’),_vm._v(” “),_c(‘p’,[_vm._v("\n html img 内嵌 image base64\n “)]),_vm._v(” “),_c(‘img’,{staticStyle:{“width”:“100px”},attrs:{“src”:_vm.imgUrl}})])],1)],1)},staticRenderFns: [], name: ‘x-message’, props: { message: String, }, data: function () { return { count: ‘2233hahaha’, imgUrl: logo } }, created: function () { console.log(’logo:’, this.imgUrl); }};message.install = function (Vue) { Vue.component(message.name, message);};export default message;//# sourceMappingURL=index.js.map构建整个组件库在支持按需引入的同时,如果还需支持完整引入整个组件库。则直接在 rollup 配置里加入一个完整的组件库入口rollup.config.js 最终配置// rollup.config.jsconst fs = require(‘fs-extra’);const path = require(‘path’);const pkg = require(”../package.json”)import vue from ‘rollup-plugin-vue2’import postcss from ‘rollup-plugin-postcss’import postcssScss from ‘postcss-scss’import autoprefixer from ‘autoprefixer’import base64 from ‘postcss-base64’import url from ‘rollup-plugin-url’import progress from ‘rollup-plugin-progress’import filesize from ‘rollup-plugin-filesize’;function isDir(dir) { return fs.lstatSync(dir).isDirectory();}const packages = {};const dir = path.join(__dirname, ‘../packages’);const files = fs.readdirSync(dir);files.forEach(file => { const absolutePath = path.join(dir, file); if (isDir(absolutePath)) { packages[file] =packages/${file}/index.js; }});const allScript = ${pkg.name}.allpackages[allScript] = packages/index.js;function createRollupConfig (file, name) { const config = { input: file, output: { file: name === allScript ? lib/index.js : lib/${name}/index.js, format: ’es’, name: name, sourcemap: true }, plugins: [ vue(), postcss({ extract: true, parser: postcssScss, plugins: [ base64({ extensions: [’.png’, ‘.jpeg’], root: ‘./packages/’, }), autoprefixer({ add: true }), ] }), url({ limit: 10 * 1024, //include: [’.svg’] }), progress(), filesize() ] } return config}const buildPackages = []for (let name in packages) { const file = packages[name] buildPackages.push(createRollupConfig(file, name))}export default buildPackages;产出的构建目录:lib ├─message │ index.js | index.css | index.js.map ├─pay │ index.js | index.css | index.js.map ├─share │ index.js | index.css | index.js.map index.js //完整组件库,包含所有组件 index.css index.js.map到这里构建部分完成,下一步,将构建后的lib目录发布到 npm:修改package.json version字段与上次不一样(如: 0.1.2),否则会提交失败修改package.json main字段为: lib/index.js发布:执行 npm publish按需引入组件组件库发布后,我们转入业务项目中npm 安装组件库,如:npm i qw-ui安装完成后,在项目node_modules文件夹下可以找到名为_qw-ui@0.1.1@qw-ui,即我们刚才发布的组件库.完整引入当我们想一次引入整个项目,而非单独引入每次组件时: 修改src/main.js,全局引入整个qw-ui,如:import Vue from ‘vue’import App from ‘./App.vue’import ElementUI from ’element-ui’;import ’element-ui/lib/theme-chalk/index.css’;import qwui from ‘qw-ui’ // 全局引入整个组件库import ‘qw-ui/lib/index.css’ // 全局载入样式Vue.config.productionTip = falseVue.use(ElementUI)Vue.use(qwui)new Vue({ render: h => h(App),}).$mount(’#app’)按需引入按需引入需要借助 babel-plugin-import,我们可以只引入需要的组件,以达到减小项目体积的目的.首先npm install babel-plugin-import –save-dev,然后再项目根目录上新建文件.babelrc.vue cli3 直接修改babel.config.js文件:// babel.config.jsmodule.exports = { presets: [ ‘@vue/app’ ], plugins: [[“import”, { “libraryName”: “qw-ui”, “customName”: (name) => { return ../lib/${name}/index; }, “style”: (name) => { return ${name}.css; } }]]}// src/main.jsimport Vue from ‘vue’import App from ‘./App.vue’import ElementUI from ’element-ui’;import ’element-ui/lib/theme-chalk/index.css’;import { message } from ‘qw-ui’ // 按需引入 message 组件Vue.config.productionTip = falseVue.use(ElementUI)Vue.use(message)new Vue({ render: h => h(App),}).$mount(’#app’)这时候已经启用了 babel-plugin-import ,插件会帮我们将import { message } from ‘qw-ui’转换成 import message from ‘qw-ui/lib/message’ 的写法。同时自动注入组件样式。~ 运行一下项目私有npm业务性组件库一般只适合于公司内部,组件或多或少的也涉及到代码安全和商业风险,所以将打包后的组件库发布到私有npm而不是发布到公网上的npm官网相对要安全很多.私有 npm 仓库可以让我们使用组件就像 npm 官方仓库里的包一样方便。私有 npm 仓库有以下一些特性:私有包托管在内部服务器或者单独的服务器上;可以同步整个官方仓库,也可以只同步需要的;下载的时候,可以让公共包走公共仓库,私有包走私有仓库;可以缓存下载过的包;对于下载,发布,有对应的权限管理。私有npm的搭建有多种方式,最简单的使用 git 仓库作为私有仓库.快速搭建和部署私有的 npm 包管理服务也可以使用 verdaccio对权限、安全性、稳定性有更高要求的可以使用 cnpmjs.org, cnpmjs.org 服务的搭建需要配合数据库使用.完! ...

February 26, 2019 · 4 min · jiezi

前端构建:3类13种热门工具的选型参考

前言在前端项目的规模和复杂性不断提升的情况下,各类构建思想和相应工具层出不穷。本文竭己所能对比了当下13个构建工具,包括Browserify、Webpack、Rollup、Grunt、Gulp和Yeoman6个广为流行的工具,FIS、Athena、WeFlow和Cooking等4个国产工具,以及三大框架:React,Vue和Angular的官方脚手架。希望能在项目初期的构建工具选型上为大家提供些参考。全览构建工具可以分为三类:模块化打包类、任务流构建类和集合型工具类(脚手架)。其中最为突出的,当属用于模块化打包的Webpack和用于任务流构建的Gulp。下面是截至2018年11月28日某时某刻,GitHub上各个工具的Star数目(听说Star数目可以造假?好生无聊的家伙们!)。前端的构建一般包括JS转码(使用Babel转ES6或TypeScript自转等)、CSS转码(Less或Sass转Css)、代码或资源的合并与压缩,基础检查和各类测试等等。这些虽与本文关系密切,但都不在讨论的范围之内。原因有二:一是实现这些功能的都是某些插件,不是工具本身,各类构建工具都是直接或间接(调用以自己的模式封装后的插件)使用它们的;二是本文介绍的是,构建方向上的类别和各类别里不同工具间的差异,与具体的操作无关。模块化打包类现在的前端项目基本是模块化的,原因就不在这多说。而模块化意味着分散,无法直接用于呈现,因此需要进行相应的打包形成一个整体。有些执行环境(Node)能自动打包各个模块,而有些(浏览器)则因为技术或其它考虑需要自行操作。模块化打包工具就是为模块化项目在浏览器上的优化呈现而服务的。模块化打包的核心是:找出依赖,打包成体。各类工具的基本运行思路便是根据已有配置,从某个文件开始,递归的找出所有与其相关的依赖模块,打包成某种类型的可直接在浏览器中运行的一个或多个新文件。这之中还可以优化输出,以实现代码分离、异步加载和长效缓存等高级功能。Browserify官网 | GitHub正如其官网介绍的,Browserify会递归的分析,项目中所有使用require引入的JS模块(包括Node内置模块)并打包,使得Node类项目能在浏览器上运行。不过对于与项目有关的其它资源,比如Css和图片等,依然需要手动管理。虽然网上已有人编写了支持此些功能的插件,但这不仅违背了设计初衷,也使配置变得杂乱。而且对于要求越来越高的单页面应用来说,它能提供的助力着实已显疲惫。Webpack官网 | 中文 | GitHub稳定版已到v4.26.0,本文以此版本为据。另附加官方的对比文档。Webpack的设计思想新颖实用,社区活跃,功能强大全面,已经是针对前端各类资源的、目前最优秀的模块化管理和打包工具。它入门简单,基本的常用功能能很快上手,并用于实际开发。但精通不易,毕竟打包已是web开发中最重要的挑战之一,必然要耗费些许精力。学习尚且不易,介绍就更为困难,得要有一本书的厚度。所幸此节不是详细介绍,只是亮点阐述,善哉善哉。入门已趋简单掌握了构建的基本思路,任意工具的入门都是较为简单的(读者批:废话)。之所以强调Webpack入门简单,是为了减轻有意者学习之前的顾虑。一方面是它刚被推出时,由于自身的概念新颖而且文档不全面,使开发者处于懵懵懂懂的状态,总感觉离真谛还差些距离。另一方面是它的体系着实庞大,仔细想想都不免胆怯。笔者初次接触时便是这些个感受。但现在不一样。吃土的日子已经远去,啃草的梦想还会远吗?大家准备好镰刀!Webpack第四版在入门上的方便性体现在三方面。一是基础功能高度集成和约定优于配置思想:安装好Webpack及其CLI后便可直接打包JS和JSON文件,与Browserify一样简单。二是官方文档详细(而且有基本同步的中文版),无论是概念的解析、实际运用的示例还是接口的展示都十分完备。三是现在使用和介绍Webpack的人已经很多了,因此网上的各路资料和相应问题的解决方案都十分丰富。你还在犹豫?一切皆模块如从官网上截取的图片所示,在Webapck眼中一切文件(.js、.css、.jpg、.woff、.csv和.ts等除了某些用于下载的静态大文件外)都是模块,都能通过与JS相似的方式被打包,并安置于合适浏览器渲染的位置。真是十分优秀的立足点。以此思想便可囊括前端会使用到的几乎所有资源,可以十分方便的统一管理和安置,更为便捷和高效。而且此思想就是为单页面应用而生的。在Webpack的另一层意境中,一个asset(各类资源)是一个模块,一个component是一个模块,一个module也是一个模块。而单页面应用的特点,不就是应用的更新不是整个页面的更新,而是某个module或component或asset的更新吗?十分的契合。有人说Webpack的缺点在服务端渲染(或说多页面应用)上。喂喂,一来别人的目标本就不在此,二是多页面应用也不需要如此复杂的支持体系。高效的构建性能单页面应用或说需要构建才能展示的应用,相比多页面应用,从每次修改到重新呈现要多经历一个构建的阶段。实际操作中,如果项目庞大而构建性能不够优化,一个小小的修改(打印某值)都会消耗5秒以上的时间,对开发者来说真是个地狱!而优化的方法不外乎两点,一是开发者优化项目的构建思路,二是构建工具优化自身的构建性能。Webpack拥有较理想的构建性能。在开发阶段,当开启了Webpack的模块热替换之后(使用webpack-dev-server会自动开启),一旦检测到文件被修改,会在应用程序运行过程中通过冒泡捕获的方式最小化替换、添加或删除模块,而无需重新加载整个页面。类似Dom渲染中的回流:如果子元素发生的大小变化,会影响兄弟元素但不影响父元素,那么父元素及其它是无需重新绘制的。而且即便完全重新构建,也会保留先前的应用程序状态,减少等待时间。活跃的社区活跃的社区可以提升系统的丰富度,降低学习与使用的成本。Webapck社区十分活跃,应用于各种需求的插件都被一一封装而可直接使用(官方也统一展示和说明了一些常用的优秀的Loader和Plugin)。不单单是其它工具的高度协调,开发中的各个阶段:搭建本地服务器、集成测试等,以及与任务流工具(Gulp、Grunt)的集成等等方面的解决或最优方案,都是丰富和全面的。基本上可以想到的需求,在这个社区中,都能直接借鉴他人已有的成果。Rollup官网 | 中文 | GitHubRollup定位为一个JS模块打包器(明指JS),主要用来构建JS库,也可服务于一些无需代码拆分和动态导入的小型应用程序。能在Webpack已稳居打包之首的情况下杀出一条血路,得到Vue、D3、Three和React等著名库的青睐,想必其着手点和性能有过人之处。Rollup本身结构简单,需要的配置项也不多,再加文档全面,所以很容易上手并全部掌握。它使用ES6本身的Module语法作为自己的标准,而不是诸如CommonJS和AMD等以前的解决方案。这意味着按照Module标准编成的代码,不仅现在可以借助Rollup打包运行,未来更能在实现此标准的浏览器上直接运行。通过Module的特性,Rollup开创了Tree-shaking功能——清除没有在项目中使用到的代码。它基于显式的import和export语句的方式,通过静态分析,排除了任何未在实际中使用的代码,能极大的减少构建于已有模块的项目体积。再加上其构建基本不添加自身的控制代码,使打包后的文件真正的达到纯净二字。想想还有点痒痒,我挠挠裆部。与 Webpack 对比Rollup和Webpack因其定位和专注点是可以共同存在并相互支持的。正如Rollup官网所说的,Rollup更适合构建独立的JS库,而Webpack为资源丰富的应用程序。虽然Webpack也增加了自己的Tree-shaking功能,但在编译后的输出代码中,简单地运行自动minifier检测未使用的变量,得到的结果是不如原生的静态分析。更何况Webpack生成的代码一定是经过自己包装后的代码——将每个模块封装在一个函数中,再置于一个包中,通过浏览器能使用的require方式逐一执行这些模块。任务流构建类基于任务的构建行为,是不在乎操作对象是否为模块化的。这类工具的目标是通过配置来解放日常需要重复的工作——转化、合并压缩和单元测试等等。有人说:这些操作Webpack和Rollup不是也能做?是的,基本能做。实际上,在用模块化构建工具的开发中,很少会用到任务流构建工具。但这绝不是说任务流工具会被取代,也不会被取代,至少多页面应用需要。再说任务流工具是十分纯粹的自动化行为,与模块化打包工具立足点就不一样,何谈取代一说。Grunt官网 | 中文 | GitHubGrunt虽是老牌构建工具,但依然被许多知名项目如WordPress、Twitter和Jquery等使用,也拥有持续更新的完整生态圈和中文文档。它是通过配置驱动——通过获取到的JSON配置执行操作,来流水线式执行相应任务。虽然在学习成本和执行效率上不出众,但如果项目原本就是通过它自动化构建的,是没有必要迁移到其它工具的。// Grunt 的配置驱动示例module.exports = function(grunt) { grunt.initConfig({ jshint: { files: [‘Gruntfile.js’, ‘src//*.js’, ’test//.js’], options: { globals: { jQuery: true } } }, watch: { files: [’<%= jshint.files %>’], tasks: [‘jshint’] } }); grunt.loadNpmTasks(‘grunt-contrib-jshint’); grunt.loadNpmTasks(‘grunt-contrib-watch’); grunt.registerTask(‘default’, [‘jshint’]);};Gulp官网 | 中文 | GitHubGulp是新型的构建工具,虽与Grunt的功能相同,但其构建过程却有三大优势。代码驱动代码驱动即通过执行实际代码驱动程序执行,与常见的配置驱动不同(Webpack、Rollup和Grunt等都是配置驱动)。从任务流构建的角度上看,代码驱动相比配置驱动有三点好处:一是高度的灵活;二是没有过多的配置项,减少学习成本;三是更方便错误的断定和异常情况的调试。// Gulp 的代码驱动示例gulp.src(’./client/templates/.jade’) .pipe(jade()) .pipe(gulp.dest(’./build/templates’)) .pipe(minify()) .pipe(gulp.dest(’./build/minified_templates’));Node流Gulp作为后来者,充分利用NodeJS流的思想进行IO操作,极大增加了大型项目的构建速度。比方说转化Scss成Css,Grunt的操作流程是:读取Scss文件、转化成Css、存储到磁盘,读取Css、压缩处理最后存储到磁盘;而Gulp得操作是:读取Scss文件、转化成Css、压缩处理最后存储到磁盘。一步到位,无需多次的IO操作。简单明了Gulp有十分精简的API。你能想到各种类型的任务,基本是通过仅有的五个可链式操作的方法实现的吗?不仅仅是学习和使用方便,编写后的功能也是一目了然。虽然代码驱动相比配置驱动,需要自己写的代码增加,但一是没增加难度只是函数名的多次重写,二是相对代码驱动的好处来说可以忽略。集合型工具类集合型工具类便是常说的脚手架,也可以看作是以模块化或任务流工具为主体的,各类常用工具的高度封装。它是一个开箱即可用的集合体,类似前后端同构时代的后端框架。它会根据你的选择,生成一个完整的、已配置好各类工具的、具有某些特定代码约定的项目框架。这些配置几乎包揽前端开发的整个流程,甚至可以集成自动化部署等后端接口。官方框架React CLI | Vue CLI | Angular CLI集合型工具一般为单页面应用服务,而单页面应用需要使用某个前端框架。无论你是用React、Vue或Angular,还是其它框架,首先得想到它是否有官方脚手架。比如Vue有Vue CLI。一般推荐有官方脚手架的直接使用官方的。因为现代前端框架一般不单独运行,需结合官方提供的其它工具,比如路由、状态管理等。而且各个框架及配件更新不断,每次更新都可能导致与其它插件的兼容问题,新的功能可能需要某些特定插件才能发挥作用。这是一项工程,仅靠个人或某些团体很难照顾周全的。而各个框架又都有意识的通过官方脚手架来充分展示新的特性,降低学习和使用的成本。我们何乐而不为呢?Yeoman官网 | GitHubYeoman是一个专为现代前端而生的、灵活通用的脚手架工具。它的运作方式和其它脚手架不同。在安装好CLI后,需要找到一个符合要求的Generator(一个npm包,相当于脚手架),使用Yeoman运行安装,生成初始化的项目。你也可以自行配置,使用Yeoman封装成符合特定需求的Generator,并发布出去。等到下次,其他人或你自己,需要生成符合此要求的项目时,便可以直接安装并使用Yeoman生成。这样有明显的两点好处:一是节省体力。在开始一个有特定需求的新项目时,如果有老项目可借鉴,一般会直接复制相关文件。但这样的复制文件可能不纯粹,即增加体积又带来安全隐患。二是在社区的支持下,很多有特殊要求的脚手架,早已有人解决并发布成Generator,是没必要自己动手的。国内其它百度 - FIS - 官网 | GitHub 微信 - WeFlow - 官网 | GitHub 京东 - Athena - 官网 | GitHub 饿了么 - Cooking(名字与公司的性质相得益彰) - 官网 | GitHub作为程序员或至各行各业,在与年龄增长速度相当的压力下,工资的高低自然成为日常性的评定标准。但在同行老友的酒桌上或某个太阳异常温煦下的小道上,能使自己为自己而不是其他事骄傲的,也肯定是“老子之前做过些什么”之类的实际付出而不是物质方面的获得。因此能够成为被公司支持的、被众多人使用的、开源框架维护团队中的程序员,多少是更为幸福的一类。这些由国内各个前端团队开发的集合型脚手架,都是基于自用在实践中得到的最为符合本身需求的产品。里面的包含内容十分丰富,不仅仅是这以上提到的前端本职工作,还有与后端的集成方案或自动化部署配置等。且流程简化,开箱即可使用。不过这些笔者都没用过,也没有打算用。不是打趣,原因很现实,有识之士可以在文章下留言。不用却依然写出的原因倒是简单:宣传,宣传即赞许和期盼;凑数,凑到13种好立个多少浮夸的标题。总结个人观点,不喜请喷,但要和蔼可亲。如果是使用某个前端框架开发应用程序,推荐框架官方的脚手架。如果是自己头脑发热想开源个JS库,推荐Rollup打包。如果不是模块化项目,又需要自动化处理一些事情,推荐Gulp作为构建工具。如果项目有特殊要求或作为核心的部件比较稀有,可以先查看Yeoman上是否有符合要求的Generator,没有就只能自食其力。最后如果你处在已有自己脚手架的公司(比如饿了么),可能要按规章制度使用Cooking为自己的仕途烹煮些吃食。肚子真饿,这种宣传饿了么会返优惠券吗?最后,如果是自食其力的搭建前人没有的脚手架,推荐使用Yeoman发布,方便你我他。 ...

November 30, 2018 · 1 min · jiezi