1

起步

关于基础知识,已经一些比较科学的理念,不需要我啰嗦说明,大家可以去看张云龙大神的github(以下简称这个为fouber的博客).我直接看这篇博客的时候: 卧槽,这tm才是构建啊。

但是兴奋完了以后,有个很现实的问题:我怎么去实现呢?然后我就放弃了。

当然,去把它实现的想法,一直都有。但是,一方面现有的工具都不是很顺手,另一方面自己的积累也不够。

前段时间简单的看了下webpack,感觉有戏,就做了些初步探讨。并写了两篇文章,文章内容现在看有些小错误,但是整体的思想都有体现了(链接文末给出)。

webpack的入门文章,强烈推荐webpack-howto,有印象有翻译版的,E文不好的,可以去找一下。

1.组件开发

1.1理念

单从形式上,静态文件不是按类型分目录,而是按页面,甚至页面里的模块来分目录。

所以每个项目的静态文件一级目录,不应该是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

当然这是一种写法上的便利,你要想写出屎一样的代码,谁都拦不住你

1.2 实现

落实到实现上,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能满足要求,但是你真正有在实际中,还是有很多细节和坑的。

  1. 首先路径问题:
    js,css的路径
    img 的路径
    css中,引用的img的路径
    发布后,cdn指向的根路径

  2. libcommon怎么处理

  3. 各种坑。比如大部分的开源项目,output.libraryTarget都设置成umd,但是这是开发库用的,开发页面的时候,umd+ externals+CommonChunkPlugin几乎一定会报错。你需要把output.libraryTarget 设置成var.

  4. 多个entry文件怎么办?开发加一个页面,就要去改一下配置文件,把entry加进去?这个显然不行,一个不够自动化,另外让大家操作配置文件,是件危险的事。

好了,说了那么多,硬广时间到了。

推销一下自己的构建的方案webpack-coc.

coc约定大于配置,根据一定的约定写代码,使用这个工具,10行左右的代码可以把一般前端应用的开发构建搞定了。

思路和我之前发的两篇文章是一致的,读完第一篇会更好的理解这个工具要做的事。

基于gulp+webpack的"约定大于配置"的构建方案探讨

基于gulp+webpack的"约定大于配置"的构建方案探讨 2


神猪_uuid
754 声望30 粉丝