webpack js 之间调用,Browserify和Gulp三者之间到底是怎样的关系

如何让jspm / WebPACK / browserify / requirejs捆绑与msdeploy?
扫码加入我们
如何让jspm / WebPACK / browserify / requirejs捆绑与msdeploy?
I currently use jspm but the same issue applies with any other build-time bundling tool. I can't figure out how to get these to play well with msdeploy.
Here's the issue:
I run jspm to produce one or more bundle files (one for each "chain" that I want).
My application uses System.import (or require or just a script tag) to start these loading.
If I were to deploy everything to a directory and xcopy from there to the deployment server everything is copacetic. However, our devops team prefers to deploy using msdeploy. For this I'm supposed to point it at a csproj. If I do this then how does msdeploy know to deploy the generated bundles?
You have to create an MSBuild project to accomplish this - one which hooks into the MSDeploy pipeline. I've provided a sample (one I'm currently using for a project) I'm likely going to release this as a Nuget package (along with some other MSBuild scripts that were written to take advantage of npm, jspm, and gulp).
The props file:
&?xml version="1.0" encoding="utf-8"?&
&Project ToolsVersion="4.0" xmlns="/developer/msbuild/2003"&
&PropertyGroup&
&CopyAllFilesToSingleFolderForPackageDependsOn&
FrontendDeploymentF
$(CopyAllFilesToSingleFolderForPackageDependsOn);
&/CopyAllFilesToSingleFolderForPackageDependsOn&
&/PropertyGroup&
&/Project&
The targets file:
&?xml version="1.0" encoding="utf-8"?&
&Project ToolsVersion="4.0" xmlns="/developer/msbuild/2003"&
&Target Name="FrontendDeploymentFiles"&
&ItemGroup&
&_CustomFiles Include="dist\**\*" /&
&_CustomFiles Include="jspm_packages\**\*" /&
&FilesForPackagingFromProject Include="%(_CustomFiles.Identity)"&
&DestinationRelativePath&%(RelativeDir)%(Filename)%(Extension)&/DestinationRelativePath&
&/FilesForPackagingFromProject&
&/ItemGroup&
&/Project&
This isn't exactly a drop-in for you as you're bundling your files, but the takeaway here is that you can define a glob pattern for your copy methods. Replace jspm_packages with whatever your bundles are (as the scripts I've provided are only for publishing to a development environment) and you should be good.
Hope this is helpful to anyone else who runs into this issue.
日12分15秒
& 2017 内容协议Webpack 扩展浅谈
26 Apr 2016
Webpack 是什么
一句话介绍,Webpack 是一个当下最热门且生态完善的 Web 前端构建工具。为什么这么说呢?从开源项目使用情况来看,Grunt, Gulp, FIS, Browserify, Webpack, Rollup 等等,最近讨论及大家推荐最多的当属 Webpack 了,实际上 Webpack 并不是最好的打包工具,有 Rollup 以函数(ES6 Modules 编码)为最小颗粒的打包工具,不过这个 Webpack v2.0+ 将实现,有带缓存编译的 FIS ,这个尤其在较大性项目中优势更加突出。但是目前围绕着 Webpack 已有非常多且成熟的加载器(Loader)以及插件(Plugin),最吸引人的当属它的热加载(内存中编译并使用 WebSocket 推送新增的内容到客户端),代码切分实现异步加载等等。
使用 Webpack 中遇到的问题
资源多个 CDN 域名支持;
缓存编译,对于没有修改的模块不进行编译;
chunkhash 在编译的时候出现内容没变但 chunkhash 变了。
Loader 是 Webpack 非常重要的一部分,因为 Webpack 本身只能处理 JavaScript 模块,所有要处理其他类型的资源就需要使用 Loader 转换,这样我们源码不管是 ES201x, CoffeeScript, JSX, Sass 等等都可以使用各自的 Loader 进行翻译并打包,图片资源可以转换为 Base64。下面是我在项目使用到的 Loader
var config = {
env: process.env.NODE_ENV,
isProd: process.env.NODE_ENV === 'production',
withCDN: process.env.WITH_CDN === 'with',
src: path.resolve(__dirname, 'src'),
dist: path.resolve(__dirname, 'dist'),
release: path.resolve(__dirname, 'staticPub'),
modules: path.resolve(__dirname, 'node_modules'),
build: function () {
return config.withCDN ? config.path.release : config.path.dist
autoprefixers: [
'Android 2.3',
'Android &= 4',
'iOS &= 7'
imgCDNs: [
'http://s1.',
'http://s2.',
'http://s3.'
var wConfig = {
loaders: [{
test: /\.js[x]?$/,
include: config.path.src,
loaders: ['babel']
test: /\.[s]?css$/,
include: config.path.src,
loaders: [
'style-loader',
'css-loader?modules&importLoaders=1&localIdentName=' + (config.isProd ? '[hash:base64:4]' : '[name]__[local]___[hash:base64:3]'),
'postcss-loader?parser=postcss-scss'
test: /\.(jpe?g|png|gif|svg)$/i,
include: config.path.src,
loaders: [
path.join(config.path.src, 'common/loaders/url-domain-loader?limit=256&name=' +
(config.isProd
? '/images/[hash].[ext]&domains=' + (config.withCDN ? encodeURIComponent(config.imgCDNs.join(',')) : '')
: '../[path][name].[ext]?[hash]'))
postcss: function (webpack) {
require('precss')(),
require('autoprefixer')({ browsers: config.autoprefixers }),
require('postcss-import')({ addDependcyTo: webpack }),
require('postcss-functions')({
functions: {
pxToRem: function (px, ui) {
px = parseInt(px)
ui = parseInt(ui) || 720
return px * 10 / ui + 'rem'
上面的配置中使用了 babel-loader, style-loader, css-loader, postcss-loader, url-domain-loader(这个是我修改了 url-loader 得来的,顾名思义这个就是处理资源域名的 loader,解决文中所提到的第一个遇到的问题),当然 Loader 的名字可以是不带 -loader 的短名。
/\.js[x]?$/ 这个表示所有的 .js, .jsx 文件都是使用 babel-loader 来处理,babel-loader 本身依赖 babel-core,即使用 Babel 翻译 ES201x 编码。
/\.[s]?css$/ 依此类推处理 .css, .scss 文件,这里使用了多个 Loader 来处理这些资源。首先资源经过 postcss-loader 处理传给 css-loader 加载到 JavaScript 中,最后由 style-loader 将其和 DOM 关联起来。在 postcss-loader 我们又使用了一些
插件来支持 Sass 翻译及多浏览器版本翻译, 可以支持类似 Sass 的编码, 用来支持 @import './xx/xx.scss', 这个非常强大,可以将 JavaScript 函数暴露给 CSS 使用,用来支持 precss 中没有函数的缺陷,autoprefixer 用来支持多浏览器版本支持,即属性名前缀或属性值前缀。css-loader 我们使用了 , CSS Modules 主要是可以将类名更换为 hash 名来避免类名产品副作用,还有就是可以优化类名长度起到压缩样式文件体积。
/\.(jpe?g|png|gif|svg)$/i 图片资源,这里使用了一个自定义 Loader 来处理的,通过这个 Loader 来解决文中提到的第一个问题,对图片资源实行多个 CDN 域名,域名通过参数传递进去,下面就是这个自定义 Loader 的全部代码。
var loaderUtils = require('loader-utils')
var mime = require('mime')
var domains = null
var index = 0
module.exports = function (content) {
if (this.cacheable) {
this.cacheable()
var query = loaderUtils.parseQuery(this.query)
var limit = (this.options && this.options.url && this.options.url.dataUrlLimit) || 0
if (query.limit) {
limit = parseInt(query.limit, 10)
var mimetype = query.mimetype || query.minetype || mime.lookup(this.resourcePath)
if (limit &= 0 || content.length & limit) {
return 'module.exports = ' + JSON.stringify('data:' + (mimetype ? mimetype + ';' : '') + 'base64,' + content.toString('base64'))
var fileLoader = require('file-loader')
var exp = fileLoader.call(this, content)
exp = exp.replace(/\\\\/g, '/')
if (!domains && query.domains) {
var ret = decodeURIComponent(query.domains).split(',')
domains = ret.length && (ret)
if (domains) {
exp = '__webpack_public_path__ = "' + domains[(index++) % domains.length] + '"; ' + exp
return exp
module.exports.raw = true
上面的代码主要工作是:根据 Loader 传过来的参数 limit 验证是否将资源转成 Base64 编码返回或者通过 file-loader 将资源写到磁盘并返回资源的相对路径,在通过 file-loader 拿到相对路径后我们在相对路径签名加上 CDN 域名就可以解决本文中第一个问题。多个 CDN 域名的算法是按资源进入顺序,如配置中有三个域名的话,第一个进入的使用第一个域名....第四个进入的使用第一个域名。这个支持多于名的 Loader 如果不配合缓存编译的话会有点问题,是由于这些资源都是异步处理的,也就是说资源的进入顺序是不确定的,这就会导致如果使用这种方式直接编译的话将会导致源码不变的情况下 hash 值会变,解决方法可以做一个缓存文件记录上次文件名和 CDN 域名以便下次使用,或者根据文件类型加 CDN 域名,或者使用缓存编译。
Webpack 的插件也非常丰富,有自带的如压缩 JavaScript 插件以及更多的第三方插件,本文中提到的第三个需要解决的问题就是使用的一个第三方插件 webpack-md5-hash 解决的。关于自己写一个插件也比较简单,如下
function HtmlPlusWebpackPlugin (options) {
// 可以在插件初始化的时候传参数进来
this.options = options || {}
HtmlPlusWebpackPlugin.prototype.apply = function (compiler, callback) {
compiler.plugin('make', function (compilation, callback) {
console.log('---------------------------------任务开始-------------------------')
callback()
compiler.plugin('emit', function (compilation, callback) {
console.log('---------------------------------生产文件前-------------------------')
// webpack config 中的参数都可通过下面两个对象获取
console.log(compiler
// 继承 compiler 对象
console.log(compilation)
callback()
module.exports = HtmlPlusWebpackPlugin
完整的事件为(make -> complie -> after-complie -> emit -> after emit)。
其他的扩展方式
最后谈谈其他的一些扩展方式,实际上最开始是想直接找一个已经实现的缓存编译插件或扩展工具来实现,但是在找到 webpack-build 工具后测试发现跟我们所期待的不一样,它是能够缓存,但是一有修改就会全量编译,最后就考虑自己实现一个简单的缓存编译。webpack-build 和 Loader 以及 Plugin 不同的是它是直接接管 Webpack 配置文件后自己进行调用的。然后我自己的扩展方式是通过缓存文件比较得到需要更新的模块后进行替换 Webpack 配置的入口信息。对于使用 Webpack 和之前没有任何区别。当修改了公共目录的资源将全部重新编译,编译过程中将本次目录中的文件修改时间保存到磁盘,还有就是要考虑新建的模块以及编译目录中被删除的模块都要进行编译。下面代码是缓存检查以及 Webpack 配置中的关键源码:
* 递归读取文件夹下所有文件修改时间戳
* @return {Object} 所有文件时间戳
_.allStats = function (dir) {
var ret = {}
var files = fs.readdirSync(dir)
files.forEach(function (file) {
var pathname = dir + '/' + file
var stat = fs.statSync(pathname)
if (stat.isDirectory()) {
ret = Object.assign(ret, _.allStats(pathname))
ret[_(pathname)] = stat.mtime.getTime()
return ret
* 读取所有源文件
* @return {Object} 缓存信息
Cache.prototype.generator = function () {
const that = this
var json = {
_t: new Date().getTime(),
var files = fs.readdirSync(that.options.src)
files.forEach(function (file) {
var pathname = that.options.src + '/' + file
json._d[file] = _.allStats(pathname)
return json
* 所有需要重新编译的文件夹
* @return {[Array]} 所有需要重新编译的文件夹
Cache.prototype.diffDirs = function () {
var that = this
var ret = []
var dotCache = that.read()
var curFiles = that._json
if (!dotCache || !dotCache._d) {
return ret
// if (JSON.stringify(curFiles._d) === JSON.stringify(dotCache._d)) {
return ret
Object.keys(curFiles._d).forEach(function (key) {
var item = curFiles._d[key]
var result = Object.keys(item).find(function (pathname) {
return (!dotCache._d[key] || !dotCache._d[key][pathname] || item[pathname] !== dotCache._d[key][pathname] || !_.exists(path.join(that.options.build, key)))
result && (ret.push(key))
return ret
// Webpack 配置文件这边根据缓存数据配置需要编译的模块入口
var _start = new Date().getTime()
var wCache = new Cache({
src: config.path.src,
build: config.path.build(),
assets: 'assets',
common: 'common'
if (wCache.exists) {
newCommon = wCache.diffCommon()
if (!newCommon) {
routes = wCache.diffRoutes(routes)
var _end = new Date().getTime()
console.log('----------------')
console.log('缓存检查耗时: ' + (_end - _start) + 'ms')
console.log('----------------')
wCache.save()
Discussions
Please enable JavaScript to view the躺下来聊聊前端自动化—node.js、npm、webpack、gulp这些鬼3 months ago5.npm怎么用呢使用npm安装插件:命令提示符执行npm install &name& [-g] [--save-dev]
5.1 &name&:node插件名称。例:npm install gulp-less --save-dev5.2、-g:全局安装。将会安装在C:\Users\Administrator\AppData\Roaming\npm,并且写入系统环境变量;
非全局安装:将会安装在当前定位目录;
全局安装可以通过命令行在任何地方调用它,本地安装将安装在定位目录的node_modules文件夹下,通过require()调用;5.3、--save:将保存配置信息至package.json(package.json是node.js的项目配置文件,在初始化文件 npm install 时会根据你配置文件中的条目进行安装);5.4、-dev:保存至package.json的devDependencies节点,不指定-dev将保存至dependencies节点;一般保存在dependencies的像这些express/ejs/body-parser等等。5.5、使用npm卸载插件:npm uninstall &name& [-g] [--save-dev]
5.6、使用npm更新插件:npm update &name& [-g] [--save-dev]
npm update [--save-dev]
// 更新全部插件
5.7、查看npm帮助:npm help5.8、当前目录已安装插件:npm lis6.选装 cnpmnpm很慢,那来cnpm吧,果然万能的淘宝,哈哈npm install cnpm -g --registry=https://registry.npm.taobao.org
安装好后看下版本号就可以直接用啦,用法和npm一致,就是npm换成cnpm就好了~三、工具搭建
Gulp、Grunt、webpack、browserify node和npm明白是干什么的了,搭建环境吗,那可以直接开敲代码了吗?no,no,no,你还需要搭建工具:1.Gulp / Grunt
简化前端流程Gulp / Grunt 是工具链、构建工具,它们能够优化前端工作流程。比如自动刷新页面、combo、压缩css、js、编译less等等。使用Gulp/Grunt,然后配置你需要的插件,就可以替代手工实现自动化工作。2.browserify / webpack
JS模块化方案browserify / webpack : 是文件打包工具,可以把项目的各种js文、css文件等打包合并成一个或多个文件,主要用于模块化方案,预编译模块的方案。因为它是预编译的,所以不需要在浏览器中加载解释器。你可在本地直接写JS,不管是 AMD / CMD / ES6 风格的模块化,它都能认识,并且编译成浏览器认识的JS。目前我只接触过gulp+webpack的项目,所以就这两个工具下载安装一下吧:3.gulp与webpack的安装安装gulpnpm install gulp -g
// 全局安装gulp
// 出现版本号即为正确安装
安装webpacknpm install webpack -g
// 全局安装webpack
webpack -v
// 出现版本号即为正确安装
全局安装过后,仍需在项目根目录进行本地安装,全局安装gulp是为了执行gulp任务,本地安装gulp则是为了调用gulp插件的功能。四、项目架构搭建1.package.json还记得上面说过的package.json嘛?package.json是基于node.js项目必不可少的配置文件,它是存放在项目根目录的普通json文件。可以通过 npm init 来新建一个package.json文件由于本文不是一篇实用性项目构建的流程文章,就不具体展开package.json的写入及配置流程了,我的第一篇blog里面有基于vue-cli的构建,可以参考。这篇文章就是想通过大体的构建过程来弄清楚各部分的功能。2.直接使用脚手架脚手架是什么:stackoverflow上的一个回答是这样的“脚手架”是一种元编程的方法,用于构建基于数据库的应用。许多MVC框架都有运用这种思想。程序员编写一份specification(规格说明书),来描述怎样去使用数据库;而由(脚手架的)编译器来根据这份specification生成相应的代码,进行增、删、改、查数据库的操作。我们把这种模式称为"脚手架",在脚手架上面去更高效的建造出强大的应用! 我的理解呢,脚手架就是给你的项目先打个架子,写个框子,然后你按着写入的方式去一点点填充满你的程序。安装vue脚手架npm install
根据webpack创建项目vue init webpack 项目名字&项目名不能用中文&
react的脚手架则是
等,有很多模版可以自己选择,这样就避免了自己构建那么多复杂的流程。五、总结一下搭建环境:node.js 等搭建工具: Gulp、Grunt、webpack、browserify 等框架:React、vue、Angular等库:jQuery、Prototype等插件:太多了……写到这也差不多了,要不然越写越偏,马上就开始建项目了这是……不知道看完这篇文章你明白node,npm这些都是做什么的了吗,其实…… 会用就行了(捂脸)。前端自动化算是前段工程化的开端,然而还有模块化、组件化、规范化等等一系列,路漫漫而修远,脚踏实地慢慢走吧~可能过一阵就会自己练习一个react的项目,到时候会记录下来,然后做一个从头到尾的项目流程。91收藏分享举报文章被以下专栏收录边学边记,有则改之,无则加勉推荐阅读{&debug&:false,&apiRoot&:&&,&paySDK&:&https:\u002F\\u002Fapi\u002Fjs&,&wechatConfigAPI&:&\u002Fapi\u002Fwechat\u002Fjssdkconfig&,&name&:&production&,&instance&:&column&,&tokens&:{&X-XSRF-TOKEN&:null,&X-UDID&:null,&Authorization&:&oauth c3cef7c66aa9e6a1e3160e20&}}{&database&:{&Post&:{&&:{&isPending&:false,&contributes&:[{&sourceColumn&:{&lastUpdated&:,&description&:&等我写完文章再回来写介绍……&,&permission&:&COLUMN_PUBLIC&,&memberId&:9314651,&contributePermission&:&COLUMN_PUBLIC&,&translatedCommentPermission&:&all&,&canManage&:true,&intro&:&边学边记,有则改之,无则加勉&,&urlToken&:&lynn-blog&,&id&:42413,&imagePath&:&v2-99fbcb7cfcf.jpg&,&slug&:&lynn-blog&,&applyReason&:&0&,&name&:&干了这碗前端酒&,&title&:&干了这碗前端酒&,&url&:&https:\u002F\\u002Flynn-blog&,&commentPermission&:&COLUMN_ALL_CAN_COMMENT&,&canPost&:true,&created&:,&state&:&COLUMN_NORMAL&,&followers&:21,&avatar&:{&id&:&v2-99fbcb7cfcf&,&template&:&https:\u002F\\u002F{id}_{size}.jpg&},&activateAuthorRequested&:false,&following&:false,&imageUrl&:&https:\u002F\\u002Fv2-99fbcb7cfcf_l.jpg&,&articlesCount&:4},&state&:&accepted&,&targetPost&:{&titleImage&:&https:\u002F\\u002Fv2-4aec4bf8f5c304a4649c7aedfccf7053_r.jpg&,&lastUpdated&:,&imagePath&:&v2-4aec4bf8f5c304a4649c7aedfccf7053.jpg&,&permission&:&ARTICLE_PUBLIC&,&topics&:[225,],&summary&:&每次在文章前面总想bb叨些废话。从3月入门到如今仰头圆月的8月半,5个半月就决定了我未来几年的职业方向甚至说是未来几年的生活重心,选择和遇见真是个奇妙的事情,就像原本不合时宜的胃疼和恰如其分而来的草莓味奥利奥…… 在学习前端的前两个半月,按部就…&,&copyPermission&:&ARTICLE_COPYABLE&,&translatedCommentPermission&:&all&,&likes&:0,&origAuthorId&:0,&publishedTime&:&T23:07:06+08:00&,&sourceUrl&:&&,&urlToken&:,&id&:3581090,&withContent&:false,&slug&:,&bigTitleImage&:true,&title&:&躺下来聊聊前端自动化—node.js、npm、webpack、gulp这些鬼&,&url&:&\u002Fp\u002F&,&commentPermission&:&ARTICLE_ALL_CAN_COMMENT&,&snapshotUrl&:&&,&created&:,&comments&:0,&columnId&:0,&content&:&&,&parentId&:0,&state&:&ARTICLE_PUBLISHED&,&imageUrl&:&https:\u002F\\u002Fv2-4aec4bf8f5c304a4649c7aedfccf7053_r.jpg&,&author&:{&bio&:&空有一颗想做厨子心的程序员&,&isFollowing&:false,&hash&:&c6e880d996f5fb737a7e2f&,&uid&:04,&isOrg&:false,&slug&:&yu-qun-20-98&,&isFollowed&:false,&description&:&有梦想 就可以玩世不恭&,&name&:&鱼群&,&profileUrl&:&https:\u002F\\u002Fpeople\u002Fyu-qun-20-98&,&avatar&:{&id&:&v2-ff895dde0be0bc769698&,&template&:&https:\u002F\\u002F50\u002F{id}_{size}.jpg&},&isOrgWhiteList&:false,&isBanned&:false},&memberId&:9314651,&excerptTitle&:&&,&voteType&:&ARTICLE_VOTE_CLEAR&},&id&:764321}],&title&:&躺下来聊聊前端自动化—node.js、npm、webpack、gulp这些鬼&,&author&:&yu-qun-20-98&,&content&:&\u003Cp\u003E 每次在文章前面总想bb叨些废话。从3月入门到如今仰头圆月的8月半,5个半月就决定了我未来几年的职业方向甚至说是未来几年的生活重心,选择和遇见真是个奇妙的事情,就像原本不合时宜的胃疼和恰如其分而来的草莓味奥利奥……\u003C\u002Fp\u003E\u003Cp\u003E 在学习前端的前两个半月,按部就班的html、css、js、jq,恩,页面很好看了。然而一个周末的vue课程,当超哥带我们敲下cmd打开这个小小的黑框子时世界就不一样了,哦,当时并没有被node.js这项伟大的发明折服,而是在接下的时间内被不断地折磨,包括初入公司打开terminal配置的那一堆php乱七八糟的东西,这tm什么鬼,我们好好打开atom敲个html页面配个css,js文件不就好了吗?ok、ok,我用……直到一次在公司做项目调接口一直报错,还是php的错,拖了很久,结果是我重启电脑没有kill掉php5.6版本的原因。你在工作的时候就不再是学生了,不会 就是你的错,可能你确实是不知道,但你总不能拿”也没人告诉我啊“这种理由过一辈子。所以,环境的搭建及使用,这些node.js、npm、webpack、gulp是什么鬼,就自己来学习一下吧。\u003C\u002Fp\u003E\u003Cp\u003E 文化的输出总会包含着个体自我的主观认知,下面的内容,基于我目前知识的局限性,无法保证纯粹的准确性,就简单讲一讲我的理解:\u003C\u002Fp\u003E\u003Cp\u003E\u003Cb\u003E一、什么是前端自动化,前端自动化能干什么?\u003C\u002Fb\u003E\u003C\u002Fp\u003E\u003Cp\u003E 你是敲代码的没错,你是一名开发人员,你的工作是创造而不是重复,那就节省出这些时间来进入前端自动化的时代:\u003C\u002Fp\u003E\u003Cp\u003E1.自动编译(将less,sass等自动编译)\u003C\u002Fp\u003E\u003Cp\u003E2.自动合并(将页面引入的多个js文件,或者css文件,合并为同一个且压缩)\u003C\u002Fp\u003E\u003Cp\u003E3.自动刷新(IDE保存,浏览器不用刷新,自动看到效果)\u003C\u002Fp\u003E\u003Cp\u003E4.自动部署(自动将项目打包部署到指定目录)\u003C\u002Fp\u003E\u003Cp\u003E5.自动同步(能够方便实现多个浏览器窗口,同步点击,输入,调试)\u003C\u002Fp\u003E\u003Cp\u003E既然前端自动化这么好,那就从开始吧。\u003C\u002Fp\u003E\u003Cp\u003E\u003Cbr\u003E\u003C\u002Fp\u003E\u003Cp\u003E下面以环境搭建=&工具搭建=&项目架构搭建来把这些鬼简单介绍一下:\u003C\u002Fp\u003E\u003Cp\u003E\u003Cb\u003E二、环境搭建
Node.js与npm\u003C\u002Fb\u003E\u003C\u002Fp\u003E\u003Cp\u003E\u003Ci\u003E1.Node.js环境搭建:\u003C\u002Fi\u003E\u003C\u002Fp\u003E\u003Cp\u003E Node.js是一个基于Chrome V8引擎的javascript的运行环境,其特点是单线程、事件驱动,非阻塞I\u002FO模型,非常轻便高效,其包管理工具npm,是全球最大的开源库生态系统。\u003C\u002Fp\u003E\u003Cp\u003E\u003Ci\u003E2.Node.js是做什么的呢:\u003C\u002Fi\u003E\u003C\u002Fp\u003E\u003Cp\u003E 本来浏览器在显示我们看到的网站的时候,会做很多事情,页面渲染,js渲染等等,然后node把其中js渲染的引擎拿出来,并且使用了谷歌的V8,然后在其外面又封装了一层api,让其拥有了文件读写,网络等操作,提供了一个服务端的运行环境,但却是运行的javascipt。所以说node.js给前端开发行业带来了一场工业革命。\u003C\u002Fp\u003E\u003Cp\u003E\u003Ci\u003E3.NPM是什么:\u003C\u002Fi\u003E\u003C\u002Fp\u003E\u003Cp\u003E NPM是随同NodeJS一起安装的包管理工具,能解决NodeJS代码部署上的很多问题,常见的使用场景有以下几种:\u003C\u002Fp\u003E\u003Cul\u003E\u003Cli\u003E允许用户从NPM服务器下载别人编写的第三方包到本地使用。\u003C\u002Fli\u003E\u003Cli\u003E允许用户从NPM服务器下载并安装别人编写的命令行程序到本地使用。\u003C\u002Fli\u003E\u003Cli\u003E允许用户将自己编写的包或命令行程序上传到NPM服务器供别人使用。\u003C\u002Fli\u003E\u003C\u002Ful\u003E\u003Cp\u003E\u003Ci\u003E4.Node.js与npm的安装:\u003C\u002Fi\u003E\u003C\u002Fp\u003E\u003Cp\u003E 打开\u003Ca href=\&http:\u002F\\u002F?target=https%3A\u002F\u002Fnodejs.org\u002F\& class=\& wrap external\& target=\&_blank\& rel=\&nofollow noreferrer\&\u003Enode.js官网\u003Ci class=\&icon-external\&\u003E\u003C\u002Fi\u003E\u003C\u002Fa\u003E去下载吧~安装好的node会自带npm。\u003C\u002Fp\u003E\u003Cp\u003E 打开命令提示符,执行下面两句,看一下版本号就可以了:\u003C\u002Fp\u003E\u003Cdiv class=\&highlight\&\u003E\u003Cpre\u003E\u003Ccode class=\&language-text\&\u003E\u003Cspan\u003E\u003C\u002Fspan\u003Enode -v
\u002F\u002F 查看当前node版本\nnpm -v
\u002F\u002F 查看当前npm版本\n\u003C\u002Fcode\u003E\u003C\u002Fpre\u003E\u003C\u002Fdiv\u003E\u003Cp\u003E\u003Ci\u003E5.npm怎么用呢\u003C\u002Fi\u003E\u003C\u002Fp\u003E\u003Cp\u003E使用npm安装插件:命令提示符执行\u003C\u002Fp\u003E\u003Cdiv class=\&highlight\&\u003E\u003Cpre\u003E\u003Ccode class=\&language-text\&\u003E\u003Cspan\u003E\u003C\u002Fspan\u003Enpm install &name& [-g] [--save-dev]\n\u003C\u002Fcode\u003E\u003C\u002Fpre\u003E\u003C\u002Fdiv\u003E\u003Cp\u003E5.1\u003Cb\u003E &name&\u003C\u002Fb\u003E:node插件名称。例:\u003Cb\u003Enpm install gulp-less --save-dev\u003C\u002Fb\u003E\u003C\u002Fp\u003E\u003Cp\u003E5.2、\u003Cb\u003E-g\u003C\u002Fb\u003E:全局安装。将会安装在C:\\Users\\Administrator\\AppData\\Roaming\\npm,并且写入系统环境变量;
非全局安装:将会安装在当前定位目录;
全局安装可以通过命令行在任何地方调用它,本地安装将安装在定位目录的node_modules文件夹下,通过require()调用;\u003C\u002Fp\u003E\u003Cp\u003E5.3、\u003Cb\u003E--save\u003C\u002Fb\u003E:将保存配置信息至package.json(package.json是node.js的项目配置文件,在初始化文件 npm install 时会根据你配置文件中的条目进行安装);\u003C\u002Fp\u003E\u003Cp\u003E5.4、\u003Cb\u003E-dev\u003C\u002Fb\u003E:保存至package.json的devDependencies节点,不指定-dev将保存至dependencies节点;一般保存在dependencies的像这些express\u002Fejs\u002Fbody-parser等等。\u003C\u002Fp\u003E\u003Cp\u003E5.5、使用npm卸载插件:\u003C\u002Fp\u003E\u003Cdiv class=\&highlight\&\u003E\u003Cpre\u003E\u003Ccode class=\&language-text\&\u003E\u003Cspan\u003E\u003C\u002Fspan\u003Enpm uninstall &name& [-g] [--save-dev]
\n\u003C\u002Fcode\u003E\u003C\u002Fpre\u003E\u003C\u002Fdiv\u003E\u003Cp\u003E5.6、使用npm更新插件:\u003C\u002Fp\u003E\u003Cdiv class=\&highlight\&\u003E\u003Cpre\u003E\u003Ccode class=\&language-text\&\u003E\u003Cspan\u003E\u003C\u002Fspan\u003Enpm update &name& [-g] [--save-dev] \nnpm update [--save-dev]
\u002F\u002F 更新全部插件\n\u003C\u002Fcode\u003E\u003C\u002Fpre\u003E\u003C\u002Fdiv\u003E\u003Cp\u003E5.7、查看npm帮助:\u003Cb\u003Enpm help\u003C\u002Fb\u003E\u003C\u002Fp\u003E\u003Cp\u003E5.8、当前目录已安装插件:\u003Cb\u003Enpm lis\u003C\u002Fb\u003E\u003C\u002Fp\u003E\u003Cp\u003E\u003Ci\u003E6.选装 cnpm\u003C\u002Fi\u003E\u003C\u002Fp\u003E\u003Cp\u003Enpm很慢,那来cnpm吧,果然万能的淘宝,哈哈\u003C\u002Fp\u003E\u003Cdiv class=\&highlight\&\u003E\u003Cpre\u003E\u003Ccode class=\&language-text\&\u003E\u003Cspan\u003E\u003C\u002Fspan\u003Enpm install cnpm -g --registry=https:\u002F\u002Fregistry.npm.taobao.org\n\u003C\u002Fcode\u003E\u003C\u002Fpre\u003E\u003C\u002Fdiv\u003E\u003Cp\u003E安装好后看下版本号就可以直接用啦,用法和npm一致,就是npm换成cnpm就好了~\u003C\u002Fp\u003E\u003Cp\u003E\u003Cb\u003E三、工具搭建
Gulp、Grunt、webpack、browserify \u003C\u002Fb\u003E\u003C\u002Fp\u003E\u003Cp\u003Enode和npm明白是干什么的了,搭建环境吗,那可以直接开敲代码了吗?no,no,no,你还需要搭建工具:\u003C\u002Fp\u003E\u003Cp\u003E\u003Ci\u003E1.Gulp \u002F Grunt
\u003Cb\u003E简化前端流程\u003C\u002Fb\u003E\u003C\u002Fi\u003E\u003C\u002Fp\u003E\u003Cp\u003EGulp \u002F Grunt 是工具链、构建工具,它们能够优化前端工作流程。比如自动刷新页面、combo、压缩css、js、编译less等等。使用Gulp\u002FGrunt,然后配置你需要的插件,就可以替代手工实现自动化工作。\u003C\u002Fp\u003E\u003Cp\u003E\u003Ci\u003E2.browserify \u002F webpack
\u003Cb\u003EJS模块化方案\u003C\u002Fb\u003E\u003C\u002Fi\u003E\u003C\u002Fp\u003E\u003Cp\u003Ebrowserify \u002F webpack : 是文件打包工具,可以把项目的各种js文、css文件等打包合并成一个或多个文件,主要用于模块化方案,预编译模块的方案。因为它是预编译的,所以不需要在浏览器中加载解释器。你可在本地直接写JS,不管是 AMD \u002F CMD \u002F ES6 风格的模块化,它都能认识,并且编译成浏览器认识的JS。\u003C\u002Fp\u003E\u003Cp\u003E目前我只接触过gulp+webpack的项目,所以就这两个工具下载安装一下吧:\u003C\u002Fp\u003E\u003Cp\u003E\u003Ci\u003E3.gulp与webpack的安装\u003C\u002Fi\u003E\u003C\u002Fp\u003E\u003Cp\u003E安装gulp\u003C\u002Fp\u003E\u003Cdiv class=\&highlight\&\u003E\u003Cpre\u003E\u003Ccode class=\&language-text\&\u003E\u003Cspan\u003E\u003C\u002Fspan\u003Enpm install gulp -g
\u002F\u002F 全局安装gulp\ngulp -v
\u002F\u002F 出现版本号即为正确安装\n\u003C\u002Fcode\u003E\u003C\u002Fpre\u003E\u003C\u002Fdiv\u003E\u003Cp\u003E安装webpack\u003C\u002Fp\u003E\u003Cdiv class=\&highlight\&\u003E\u003Cpre\u003E\u003Ccode class=\&language-text\&\u003E\u003Cspan\u003E\u003C\u002Fspan\u003Enpm install webpack -g
\u002F\u002F 全局安装webpack\nwebpack -v
\u002F\u002F 出现版本号即为正确安装\n\u003C\u002Fcode\u003E\u003C\u002Fpre\u003E\u003C\u002Fdiv\u003E\u003Cp\u003E全局安装过后,仍需在项目根目录进行本地安装,全局安装gulp是为了执行gulp任务,本地安装gulp则是为了调用gulp插件的功能。\u003C\u002Fp\u003E\u003Cp\u003E\u003Cb\u003E四、项目架构搭建\u003C\u002Fb\u003E\u003C\u002Fp\u003E\u003Cp\u003E1.package.json\u003C\u002Fp\u003E\u003Cp\u003E还记得上面说过的package.json嘛?package.json是基于node.js项目必不可少的配置文件,它是存放在项目根目录的普通json文件。\u003C\u002Fp\u003E\u003Cp\u003E可以通过 npm init 来新建一个package.json文件\u003C\u002Fp\u003E\u003Cp\u003E由于本文不是一篇实用性项目构建的流程文章,就不具体展开package.json的写入及配置流程了,我的第一篇blog里面有基于vue-cli的构建,可以参考。这篇文章就是想通过大体的构建过程来弄清楚各部分的功能。\u003C\u002Fp\u003E\u003Cp\u003E2.直接使用脚手架\u003C\u002Fp\u003E\u003Cp\u003E脚手架是什么:stackoverflow上的一个回答是这样的\u003C\u002Fp\u003E\u003Cp\u003E“脚手架”是一种元编程的方法,用于构建基于数据库的应用。许多MVC框架都有运用这种思想。程序员编写一份specification(规格说明书),来描述怎样去使用数据库;而由(脚手架的)编译器来根据这份specification生成相应的代码,进行增、删、改、查数据库的操作。我们把这种模式称为\&脚手架\&,在脚手架上面去更高效的建造出强大的应用! \u003C\u002Fp\u003E\u003Cp\u003E我的理解呢,脚手架就是给你的项目先打个架子,写个框子,然后你按着写入的方式去一点点填充满你的程序。\u003C\u002Fp\u003E\u003Cp\u003E安装vue脚手架\u003C\u002Fp\u003E\u003Cdiv class=\&highlight\&\u003E\u003Cpre\u003E\u003Ccode class=\&language-text\&\u003E\u003Cspan\u003E\u003C\u002Fspan\u003Enpm install
vue-cli \n\u003C\u002Fcode\u003E\u003C\u002Fpre\u003E\u003C\u002Fdiv\u003E\u003Cp\u003E根据webpack创建项目\u003C\u002Fp\u003E\u003Cdiv class=\&highlight\&\u003E\u003Cpre\u003E\u003Ccode class=\&language-text\&\u003E\u003Cspan\u003E\u003C\u002Fspan\u003Evue init webpack 项目名字&项目名不能用中文&\n\u003C\u002Fcode\u003E\u003C\u002Fpre\u003E\u003C\u002Fdiv\u003E\u003Cp\u003Ereact的脚手架则是 \u003Ca href=\&http:\u002F\\u002F?target=https%3A\\u002Ffacebookincubator\u002Fcreate-react-app\u002F\& class=\& wrap external\& target=\&_blank\& rel=\&nofollow noreferrer\&\u003Ecreate-react-app\u003Ci class=\&icon-external\&\u003E\u003C\u002Fi\u003E\u003C\u002Fa\u003E 等,有很多模版可以自己选择,这样就避免了自己构建那么多复杂的流程。\u003C\u002Fp\u003E\u003Cp\u003E\u003Cb\u003E五、总结一下\u003C\u002Fb\u003E\u003C\u002Fp\u003E\u003Cp\u003E搭建环境:node.js 等\u003C\u002Fp\u003E\u003Cp\u003E搭建工具: Gulp、Grunt、webpack、browserify 等\u003C\u002Fp\u003E\u003Cp\u003E框架:React、vue、Angular等\u003C\u002Fp\u003E\u003Cp\u003E库:jQuery、Prototype等\u003C\u002Fp\u003E\u003Cp\u003E插件:太多了……\u003C\u002Fp\u003E\u003Cp\u003E\u003Cbr\u003E\u003C\u002Fp\u003E\u003Cp\u003E写到这也差不多了,要不然越写越偏,马上就开始建项目了这是……不知道看完这篇文章你明白node,npm这些都是做什么的了吗,其实…… 会用就行了(捂脸)。前端自动化算是前段工程化的开端,然而还有模块化、组件化、规范化等等一系列,路漫漫而修远,脚踏实地慢慢走吧~可能过一阵就会自己练习一个react的项目,到时候会记录下来,然后做一个从头到尾的项目流程。\u003C\u002Fp\u003E\u003Cp\u003E\u003C\u002Fp\u003E\u003Cp\u003E\u003C\u002Fp\u003E\u003Cp\u003E\u003C\u002Fp\u003E\u003Cp\u003E\u003C\u002Fp\u003E\u003Cp\u003E\u003C\u002Fp\u003E\u003Cp\u003E\u003C\u002Fp\u003E&,&updated&:new Date(&T15:07:06.000Z&),&canComment&:false,&commentPermission&:&anyone&,&commentCount&:37,&collapsedCount&:0,&likeCount&:91,&state&:&published&,&isLiked&:false,&slug&:&&,&isTitleImageFullScreen&:true,&rating&:&none&,&titleImage&:&https:\u002F\\u002Fv2-4aec4bf8f5c304a4649c7aedfccf7053_r.jpg&,&links&:{&comments&:&\u002Fapi\u002Fposts\u002F2Fcomments&},&reviewers&:[],&topics&:[{&url&:&https:\u002F\\u002Ftopic\u002F&,&id&:&&,&name&:&前端开发&},{&url&:&https:\u002F\\u002Ftopic\u002F&,&id&:&&,&name&:&前端入门&},{&url&:&https:\u002F\\u002Ftopic\u002F&,&id&:&&,&name&:&前端工程化&}],&adminClosedComment&:false,&titleImageSize&:{&width&:1733,&height&:1733},&href&:&\u002Fapi\u002Fposts\u002F&,&excerptTitle&:&&,&tipjarState&:&inactivated&,&annotationAction&:[],&sourceUrl&:&&,&pageCommentsCount&:37,&hasPublishingDraft&:false,&snapshotUrl&:&&,&publishedTime&:&T23:07:06+08:00&,&url&:&\u002Fp\u002F&,&lastestLikers&:[{&bio&:&码农互联网学生&,&isFollowing&:false,&hash&:&d06f496abd1a96b8d047e&,&uid&:963300,&isOrg&:false,&slug&:&yang-guang-35-53&,&isFollowed&:false,&description&:&&,&name&:&阳光&,&profileUrl&:&https:\u002F\\u002Fpeople\u002Fyang-guang-35-53&,&avatar&:{&id&:&v2-6a40a8bc96c1a3224cae&,&template&:&https:\u002F\\u002F50\u002F{id}_{size}.jpg&},&isOrgWhiteList&:false,&isBanned&:false},{&bio&:&程序猿&,&isFollowing&:false,&hash&:&c8b5cde13ca&,&uid&:789400,&isOrg&:false,&slug&:&wang-chao-qun-168&,&isFollowed&:false,&description&:&&,&name&:&王超群168&,&profileUrl&:&https:\u002F\\u002Fpeople\u002Fwang-chao-qun-168&,&avatar&:{&id&:&v2-7bbf58b51547afbacf8b42&,&template&:&https:\u002F\\u002F50\u002F{id}_{size}.jpg&},&isOrgWhiteList&:false,&isBanned&:false},{&bio&:&进来看看&,&isFollowing&:false,&hash&:&4a31bb4c00f9a2b880d7f8&,&uid&:96,&isOrg&:false,&slug&:&ji-lin-26-89&,&isFollowed&:false,&description&:&&,&name&:&纪林&,&profileUrl&:&https:\u002F\\u002Fpeople\u002Fji-lin-26-89&,&avatar&:{&id&:&da8e974dc&,&template&:&https:\u002F\\u002F{id}_{size}.jpg&},&isOrgWhiteList&:false,&isBanned&:false},{&bio&:&飞船租售 \u002F 星际船票代理 \u002F 三体系统运维&,&isFollowing&:false,&hash&:&ef73c38ec0bc766fff69fdd&,&uid&:88,&isOrg&:false,&slug&:&yushiying&,&isFollowed&:false,&description&:&晕船&,&name&:&atoi&,&profileUrl&:&https:\u002F\\u002Fpeople\u002Fyushiying&,&avatar&:{&id&:&36e67a9f49fd14be76cec&,&template&:&https:\u002F\\u002F50\u002F{id}_{size}.jpg&},&isOrgWhiteList&:false,&isBanned&:false},{&bio&:&程序员&,&isFollowing&:false,&hash&:&f90f3c7c21996dbc22d1f0&,&uid&:763600,&isOrg&:false,&slug&:&zhong-li-jun-12-26&,&isFollowed&:false,&description&:&&,&name&:&钟李俊&,&profileUrl&:&https:\u002F\\u002Fpeople\u002Fzhong-li-jun-12-26&,&avatar&:{&id&:&v2-cf49cab043cc960a2d8176&,&template&:&https:\u002F\\u002F50\u002F{id}_{size}.jpg&},&isOrgWhiteList&:false,&isBanned&:false}],&summary&:&每次在文章前面总想bb叨些废话。从3月入门到如今仰头圆月的8月半,5个半月就决定了我未来几年的职业方向甚至说是未来几年的生活重心,选择和遇见真是个奇妙的事情,就像原本不合时宜的胃疼和恰如其分而来的草莓味奥利奥…… 在学习前端的前两个半月,按部就…&,&reviewingCommentsCount&:0,&meta&:{&previous&:null,&next&:null},&annotationDetail&:null,&commentsCount&:37,&likesCount&:91,&FULLINFO&:true}},&User&:{&yu-qun-20-98&:{&isFollowed&:false,&name&:&鱼群&,&headline&:&有梦想 就可以玩世不恭&,&avatarUrl&:&https:\u002F\\u002F50\u002Fv2-ff895dde0be0bc769698_s.jpg&,&isFollowing&:false,&type&:&people&,&slug&:&yu-qun-20-98&,&bio&:&空有一颗想做厨子心的程序员&,&hash&:&c6e880d996f5fb737a7e2f&,&uid&:04,&isOrg&:false,&description&:&有梦想 就可以玩世不恭&,&badge&:{&identity&:null,&bestAnswerer&:null},&profileUrl&:&https:\u002F\\u002Fpeople\u002Fyu-qun-20-98&,&avatar&:{&id&:&v2-ff895dde0be0bc769698&,&template&:&https:\u002F\\u002F50\u002F{id}_{size}.jpg&},&isOrgWhiteList&:false,&isBanned&:false}},&Comment&:{},&favlists&:{}},&me&:{},&global&:{&experimentFeatures&:{&ge3&:&ge3_9&,&ge2&:&ge2_1&,&nwebStickySidebar&:&sticky&,&androidPassThroughPush&:&all&,&newMore&:&new&,&liveReviewBuyBar&:&live_review_buy_bar_2&,&liveStore&:&ls_a2_b2_c1_f2&,&searchHybridTabs&:&pin-3&,&isOffice&:&false&,&homeUi2&:&default&,&remixOneKeyPlayButton&:&headerButton&,&marketTab&:&market_tab_old&,&qrcodeLogin&:&qrcode&,&isShowUnicomFreeEntry&:&unicom_free_entry_off&,&newMobileColumnAppheader&:&new_header&,&androidDbRecommendAction&:&open&,&zcmLighting&:&zcm&,&favAct&:&default&,&appStoreRateDialog&:&close&,&mobileQaPageProxyHeifetz&:&m_qa_page_nweb&,&default&:&None&,&wechatShareModal&:&wechat_share_modal_show&,&qaStickySidebar&:&sticky_sidebar&,&androidProfilePanel&:&panel_b&,&nwebWriteAnswer&:&default&}},&columns&:{&next&:{}},&columnPosts&:{},&columnSettings&:{&colomnAuthor&:[],&uploadAvatarDetails&:&&,&contributeRequests&:[],&contributeRequestsTotalCount&:0,&inviteAuthor&:&&},&postComments&:{},&postReviewComments&:{&comments&:[],&newComments&:[],&hasMore&:true},&favlistsByUser&:{},&favlistRelations&:{},&promotions&:{},&draft&:{&titleImage&:&&,&titleImageSize&:{},&isTitleImageFullScreen&:false,&canTitleImageFullScreen&:false,&title&:&&,&titleImageUploading&:false,&error&:&&,&content&:&&,&draftLoading&:false,&globalLoading&:false,&pendingVideo&:{&resource&:null,&error&:null}},&drafts&:{&draftsList&:[],&next&:{}},&config&:{&userNotBindPhoneTipString&:{}},&recommendPosts&:{&articleRecommendations&:[],&columnRecommendations&:[]},&env&:{&edition&:{},&isAppView&:false,&appViewConfig&:{&content_padding_top&:128,&content_padding_bottom&:56,&content_padding_left&:16,&content_padding_right&:16,&title_font_size&:22,&body_font_size&:16,&is_dark_theme&:false,&can_auto_load_image&:true,&app_info&:&OS=iOS&},&isApp&:false},&message&:{&newCount&:0},&pushNotification&:{&newCount&:0}}}

我要回帖

更多关于 pragma pack 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信