关于基础知识,已经一些比较科学的理念,不需要我啰嗦说明,大家可以去看 张云龙大神的github (以下简称这个为 fouber的博客
).我直接看这篇博客的时候: 卧槽,这tm才是构建啊。
但是兴奋完了以后,有个很现实的问题:我怎么去实现呢?然后我就放弃了。
当然,去把它实现的想法,一直都有。但是,一方面现有的工具都不是很顺手,另一方面自己的积累也不够。
前段时间简单的看了下 webpack
,感觉有戏,就做了些初步探讨。并写了两篇文章,文章内容现在看有些小错误,但是整体的思想都有体现了(链接文末给出)。
webpack的入门文章,强烈推荐 webpack-howto ,有印象有翻译版的,E文不好的,可以去找一下。
单从形式上,静态文件不是按类型分目录,而是按页面,甚至页面里的模块来分目录。
所以每个项目的静态文件一级目录,不应该是 js
, css
, img
.这种目录结构随着项目变大,找文件就让你很烦躁。比如有个页面,要下线了,那么它对应的js,css,img应该也要删除,但是上面的目录结构,你很难去确定某个静态文件是不是只有这个页面引用。比较好的情况是,能够很容易的辨别能不能删,如果误删,构建的时候就报错。当然好处还有很多,这个 fouber的博客
里有很多说明,就不赘述了。
那么写一个首页,我可能希望这样写:
/index /header header.js header.less header.jsx img/ 1.png,2.png... /body ..类似header /footer ..类似header index.less logo.png index.entry.js
其中 index.entry.js
是首页的入口文件。一般就是引入各个模块的文件和自己另外的一些资源文件,然后再加一些整合的逻辑
//index.entry.js中 import React from 'react' import header from './header/header.js' import './index.less' import './logo.png' //下面是业务逻辑代码 //按需加载可以使用require.ensure 或者 bundle-loader
当然这是一种写法上的便利,你要想写出屎一样的代码,谁都拦不住你
落实到实现上,webpack通过各种loader去实现各种类型资源的解析、引用、打包。这个配置好loaders就ok了。
不过这里,展开来讲,有很多细节: 比如图片的路径。打包后的 相对路径
和你开发时候的相对路径可能是不一样的。实际上,路径问题,很容易错误,不过 webpack
以及各种 loader
提供的选项还比较细,都有可行的解决方式。一个比较典型的loaders配置
loaders: [ { test: /[/.jsx|/.js ]$/, exclude: /node_modules/, loader: "babel-loader?stage=0&optional[]=runtime" }, { test: //.css$/, loader: ExtractTextPlugin.extract('style-loader', 'css-loader') }, { test: //.less$/, loader: ExtractTextPlugin.extract('style-loader', 'css-loader?sourceMap!postcss-loader!less-loader') }, { test: //.(png|jpg|gif)$/, loader: 'url-loader?limit=10000&name=img/[name]-[hash].[ext]' } ]
静态资源管理系统 = 资源表 + 资源加载框架
资源加载框架,实际webpack已经基本把活全做了。
构建的时候,你的代码就表明了它所依赖的东西,异步加载通过 code splitting 相关技术,webpack打包的时候,都帮你自动管理。
那么,你只要对每个 entry
生成资源表(我叫做它 assets-map
)就行了。使用webpack,多页面,有多个entry,多入口的配置也很简单
entry: { entryName:'entryFilePath.js', entryName1:'entryFilePath1.js' //... }
webpack打包完,会提供一个 stats
对象, webpack(config,function(err,stats){})
,这里有每个 chunk
的详细信息 ,利用这个对象,就可以去生成每个文件的 assets-map
。不过那么重要的东西,当然已经有开源的东西了, assets-webpack-plugins .下面是生成了 assets-map
的一个例子。hash戳是加载在后面当queryString还是当作文件名的一部分,都可以配置。
{ "webpack-coc/lib": { "js": "/dist/webpack-coc/lib.js?v=ac46dc0f05a4cc181b911ad1b8058f71e6fbc87d" }, "webpack-coc/common": { "js": "/dist/webpack-coc/common.js?v=ef0de9675a8837209c4f", "css": "/dist/webpack-coc/common.css?v=ef0de9675a8837209c4f" }, "webpack-coc/index/index.entry": { "js": "/dist/webpack-coc/index/index.entry.js?v=7e28f5d80d5d6001e7fe", "css": "/dist/webpack-coc/index/index.entry.css?v=7e28f5d80d5d6001e7fe" }, "webpack-coc/contact/contact.entry": { "js": "/dist/webpack-coc/contact/contact.entry.js?v=b2e27e29b6fd11004a49" }, "webpack-coc/other/other.entry": { "js": "/dist/webpack-coc/other/other.entry.js?v=95edb51bcbc304ccd1ad" } }
后端解析下这个json,就可以在页面中生成和文件内容相关的唯一的资源文件的路径。
上面两点的说明,表明 webpack
能满足要求,但是你真正有在实际中,还是有很多细节和坑的。
首先路径问题:
js,css的路径
img 的路径
css中,引用的img的路径
发布后,cdn指向的根路径
lib
和 common
怎么处理
各种坑。比如大部分的开源项目, output.libraryTarget
都设置成 umd
,但是这是开发库用的,开发页面的时候, umd
+ externals
+ CommonChunkPlugin
几乎一定会报错。你需要把output.libraryTarget 设置成 var
.
多个entry文件怎么办?开发加一个页面,就要去改一下配置文件,把entry加进去?这个显然不行,一个不够自动化,另外让大家操作配置文件,是件危险的事。
好了,说了那么多,硬广时间到了。推销一下自己的 构建的方案 .
思路和我之前发的两篇文章是一致的,读完 第一篇
会更好的理解这个工具要做的事。
基于gulp+webpack的"约定大于配置"的构建方案探讨
基于gulp+webpack的"约定大于配置"的构建方案探讨 2