前端工程化-npm-gulp-webpack

题目1: 如何全局安装一个 node 应用?

Node模块采用npm install命令安装。

每个模块可以“全局安装”,也可以“本地安装”。“全局安装”指的是将一个模块安装到系统目录中,各个项目都可以调用。一般来说,全局安装只适用于工具模块,比如eslintgulp。“本地安装”指的是将一个模块下载到当前项目的node_modules子目录,然后只有在项目目录之中,才能调用这个模块。

# 本地安装
 npm install 

# 全局安装
 npm install -g 

# npm更新最新版本
cnpm install npm@lastest -g

如果下载速度比较慢,可以使用淘宝的镜像

//先执行下面命令
npm install -g cnpm --registry=https://registry.npm.taobao.org

//以后安装就用 cnpm 代替 npm
cnpm install -g xxx
install 可以缩写成 i

题目2: package.json 有什么作用?

命令行npm init 可以初始化生成一个package.json

package.json 是一个 json格式的文件,用来记录当前的npm 包的相关信息,如

name:包的名字
version:版本号
description:描述
main:包的入口文件
script: 运行脚本命令的npm命令行缩写
author: 作者
license: 版权信息
dependencies:项目运行依赖,发布的时候,不需要发布依赖的包,只要发布其名字,别人下载的时候,会自动下载依赖的包。
devDependencies:开发依赖,只有自己本地开发时候用的依赖包,发布以后别人不能用。

{
"name": "packageName", 
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
  "test": "echo \"Error: no test specified\" && exit 1"
},
"author": "cg",
"license": "ISC",
"dependencies": {},
"devDependencies": {}
}

题目3: npm install --save app 与 npm install --save-dev app有什么区别?

命令行参数

当你为你的模块安装一个依赖模块时,正常情况下你得先安装他们,在模块根目录下npm install module-name,然后连同版本号手动将他们添加到模块配置文件package.json中的依赖里(dependencies)

-savesave-dev可以省掉你手动修改package.json文件的步骤。

npm install module-name -save

自动把模块和版本号添加到dependencies部分。

npm install module-name -save-dev

自动把模块和版本号添加到devdependencies部分。

配置文件

package.json提供了三种依赖关系定义:

  • dependencies
  • peerDependencies
  • devDependencies

devDependencies是开发时依赖,比如你模块用了mocha测试框架,那么你的模块的开发就依赖mocha,如果别人想为你的模块贡献代码,他就需要安装mocha。但是只是使用你的模块的人,就不需要mocha

peerDependencies是为插件准备的。比如grunt的插件,里面没有require(“grunt”),所以用dependencies会有问题。所以需要单独列出。

题目4: node_modules的查找路径是怎样的?

  • 先从当前目录下查找node_modules文件夹,如果没有,则到父级文件夹查找node_modules文件夹,直至查找到根目录。

题目5: npm3与 npm2相比有什么改进?yarn和 npm 相比有什么优势? (选做题目)

模块和包

很多时候我们并不是很区分模块和包,因为我们一般使用场景就是 npm install xxx,然后在文件里直接require('xxx')
但是考虑到很多时候我们也可以随意 require 一个本地自己写的 JS 文件,只要其按照CommonJS 规范 export即可,因此这里需要严格区分下:

  • 模块:符合 CommonJS 规范的文件
  • 包:一个包含 package.json以及入口文件的文件夹

这里也不是绝对这样定义的,不过最终表现出来的就是这些,而 npm 的所有的管理的对象都必须包含 package.json 文件,用于模块确定依赖关系。
说了这么多,只是为了强调:npm是包管理器。

npm2 问题

npm2 安装依赖的时候比较简单直接,直接按照包依赖的树形结构下载填充本地目录结构。
因为 npm 设计的初衷就是考虑到了包依赖的版本错综复杂的关系,同一个包因为被依赖的关系原因会出现多个版本,简单地填充结构保证了无论是安装还是删除都会有统一的行为和结构。
比如一个 App 里模块 A 和 C 都依赖 B,无论被依赖的 B 是否是同一个版本,都会生成对应结构:


前端工程化-npm-gulp-webpack_第1张图片

于是缺陷就凸显出来了,太深的目录树结构会严重影响效率,甚至在 Windows 下可能会超出系统路径限制的长度。另外,在 Windows 有删 node_modules 目录经历的可能都经历过漫长的等待。

npm3 解决方式

针对 npm2的问题,npm3加了点算法,直白的解释就是:npm install
时会按照 package.json 里依赖的顺序依次解析,遇到新的包就把它放在第一级目录,后面如果遇到一级目录已经存在的包,会先判断版本,如果版本一样则忽略,否则会按照npm2 的方式依次挂在依赖包目录下
还是刚刚的栗子,可以看下npm2npm3生成的结构对比:

前端工程化-npm-gulp-webpack_第2张图片

试想,在包版本差异化不太严重的情况下,这种构建方式会几乎把所有包放在一级目录下,很大程度上提升了效率以及节省了部分磁盘空间。
其实,npm3 这种方式在理论上其实会趋于一种平稳的状态,因为你可能会说, npm3 在极端情况下也可能退化为 npm2 的行为,不过这种情况在一般情况下是可以忽略的。 npm3 还有个优点,就是在动态安装更新包的时候,是可以进一步调整目录结构的,比如某种依赖已经如下:
前端工程化-npm-gulp-webpack_第3张图片

具体依赖细节我们不用追究,假设 E_v1.0 模块是依赖 B_v1.0 的,此时我们更新 E 到 v2.0,假设此时依赖 B_v2.0 了,那么最终生成的结构会是如下:
前端工程化-npm-gulp-webpack_第4张图片

是不是觉得很多冗余?其实只需执行下 npm dedupe
就会变成如下结构:
前端工程化-npm-gulp-webpack_第5张图片

这已经很接近我们理想的使用场景了!

npm3 新的问题

你以为就这么完了吗?注意到上面提到的npm3会按照package.json 的顺序解析目录树,试着看下下面的场景:

前端工程化-npm-gulp-webpack_第6张图片

对应的 dependencies为:

"dependencies": { "mod-a": "^1.0.0", "mod-c": "^1.0.0", "mod-d": "^1.0.0", "mod-e": "^1.0.0"}

如果恰好 A_v1.0 依赖 B_v1.0,然后我们本地升级了 A 到 v2.0,假设此时依赖 B_v2.0,那么此时目录结构会变成:

前端工程化-npm-gulp-webpack_第7张图片

而此时部署到测试平台呢?因为 mod-a 在第一个,所以会优先解析,也就是 B_v2.0 会优先占据一级目录,最终可能目录结构为:
前端工程化-npm-gulp-webpack_第8张图片

开发环境和测试环境的 node_modules目录结构不一样了!!这个问题很可能会导致一些很微妙的问题,而且很难调试。如何解决呢?就是本地每次安装或者升级包后,完整删除 node_modules目录然后再 install一次……(感觉比 npm2 还粗暴)

新的工具 yarn

除了上面的问题,还有个严重的问题。npm 在使用的时候大多是用语义化版本号管理包依赖的,比如 ~1.0.0
表示只更新补丁,但是世界辣么大,什么人没有?说不定哪个开发者就在 patch version 上就搞了major的升级,即使你本地使用固定版本号也无济于事。
当然,后面 npm 也有 shrinkwrap 机制来保证这种一致性,不过说实话 npm-shrinkwrap.json 略难看,基本属于给 npm 打补丁,让我在一个项目引入这个几乎无法 review 的文件肯定会不开心的。
太多因素导致了 npm 已经步履维艰了,估计 Facebook 也累了吧,于是前不久搞了yarn用来替代npm 了。
我觉得yarn革命性的更改在于其改变了构建的步骤,其它有点都是新构建方式的副产物,yarn构建步骤如下:

  • Resolution: 向仓库请求依赖关系
  • Fetching: 看看本地缓存了没有,否则把包拉到缓存里
  • Linking: 直接全部从缓存里构建好目录树放到 node_modules 里

这里的缓存机制很像 mvn 之类的,而且其还引入了lockfile 用于锁定版本号,这很类似shrinkwrap,不过格式比npm-shrinkwrap.json 更好 review。除了这些特别明显的改进,还有很多体验上的提升,具体可以看官方博客。

题目6: webpack是什么?和其他同类型工具比有什么优势?

WebPack可以看做是模块打包机:它做的事情是,分析你的项目结构,找到JavaScript模块以及其它的一些浏览器不能直接运行的拓展语言(ScssTypeScript等),并将其打包为合适的格式以供浏览器使用。

WebPack和Grunt以及Gulp相比有什么特性

其实 Webpack 和另外两个并没有太多的可比性,Gulp/Grunt 是一种能够优化前端的开发流程的工具,而WebPack 是一种模块化的解决方案,不过Webpack 的优点使得 Webpack 可以替代 Gulp/Grunt 类的工具。
GruntGulp 的工作方式是:在一个配置文件中,指明对某些文件进行类似编译,组合,压缩等任务的具体步骤,这个工具之后可以自动替你完成这些任务。

前端工程化-npm-gulp-webpack_第9张图片

** Grunt
Gulp** 的工作流程

Webpack的工作方式是:把你的项目当做一个整体,通过一个给定的主文件(如:index.js),Webpack将从这个文件开始找到你的项目的所有依赖文件,使用loaders处理它们,最后打包为一个浏览器可识别的JavaScript文件。

前端工程化-npm-gulp-webpack_第10张图片
Webpack工作方式

如果实在要把二者进行比较,Webpack的处理速度更快更直接,能打包更多不同类型的文件。

题目7:npm script是什么?如何使用?

npm允许在package.json文件里面,使用scripts字段定义脚本命令。

{
  // ...
  "scripts": {
    "build": "node build.js"
  }
}

上面代码是package.json文件的一个片段,里面的scripts字段是一个对象。它的每一个属性,对应一段脚本。比如,build命令对应的脚本是node build.js
命令行下使用npm run命令,就可以执行这段脚本。

$ npm run build

等同于执行

$ node build.js

这些定义在package.json里面的脚本,就称为 npm 脚本。它的优点很多。

  • 项目的相关脚本,可以集中在一个地方。
  • 不同项目的脚本命令,只要功能相同,就可以有同样的对外接口。用户不需要知道怎么测试你的项目,只要运行npm run test即可。
  • 可以利用 npm 提供的很多辅助功能。

查看当前项目的所有 npm 脚本命令,可以使用不带任何参数的npm run命令。

$ npm run

题目8: 使用 webpack 替换 入门-任务15中模块化使用的 requriejs

github代码

题目9:gulp是什么?使用 gulp 实现图片压缩、CSS 压缩合并、JS 压缩合并

简介:

gulp 是前端开发过程中对代码进行构建的工具,是自动化项目的构建利器;她不仅能对网站资源进行优化,而且在开发过程中很多重复的任务能够使用正确的工具自动完成;使用她,我们不仅可以很愉快的编写代码,而且大大提高我们的工作效率。

gulp中文网

入门指南

  1. 全局安装 gulp:
$ npm install --global gulp
  1. 作为项目的开发依赖(devDependencies)安装:
$ npm install --save-dev gulp
  1. 在项目根目录下创建一个名为 gulpfile.js 的文件:
var gulp = require('gulp');
gulp.task('default', function() {
  // 将你的默认的任务代码放在这
});
  1. 运行 gulp:
$ gulp

默认的名为 default 的任务(task)将会被运行,在这里,这个任务并未做任何事情。

想要单独执行特定的任务(task),请输入 gulp

gulp的常用插件

var gulp=require('gulp');
var del=require('del');                         // 删除文件
var minify=require('gulp-minify-css');           //压缩CSS
var uglify=require('gulp-uglify');                // 压缩JS
var concat=require('gulp-concat');               // 合并文件
var imagemin=require('gulp-imagemin');       // 缩小图片


gulp.task('css', function() {
    gulp.src('css/*.css')
        .pipe(concat('merge.css'))
        .pipe(minify())
        .pipe(gulp.dest('dist2/css'));
})

gulp.task('js', function() {
    gulp.src('js/**/*.js')
        .pipe(concat('merge.js'))
        .pipe(uglify())
        .pipe(gulp.dest('dist2/js'));
})

gulp.task('pic', function() {
    gulp.src('images/*')
        .pipe(imagemin())
        .pipe(gulp.dest('dist2/images'));
})

gulp.task('clean', function() {
    del([
       'dist2'
    ])
 })

gulp.task('default',['css','js','pic'])

你可能感兴趣的:(前端工程化-npm-gulp-webpack)