随着前端技术的不断发展,项目的日趋复杂,为了实现代码复用及方便后期的项目维护,模块化在开发中变的必不可少.而目前更通用的是browserify、webpack等技术,是一种预编译模块的方案,而webpack相对于browserify更加强大,也是目前主流的自动模块化打包的工具,本次主要讲解webpack在前端模块化开发中的作用及实际的应用;
      本文转自IT培训机构-学领未来

一、前端模块化规范介绍

1.1      CommonJS规范

CommonJS是适用于服务器端的,Node.js执行环境就是采用的CommonJS模式。它是同步加载不同模块文件,之所以采用同步,是因为模块文件都存放在服务器的各个硬盘上,实际的加载时间就是硬盘的文件读取时间。

(1) 一个单独的文件就是一个模块。每一个模块都是一个单独的作用域,也就是说,在该模块内部定义的变量,无法被其他模块读取,除非定义为global对象的属性。

(2) 输出模块变量的最好方法是使用module.exports对象。

(3) 加载模块使用require方法,该方法读取一个文件并执行,返回文件内部的module.exports对象。

1.2      AMD模块化规范

AMD是"Asynchronous Module Definition"的缩写表示"异步模块定义",由于不是JavaScript原生支持,使用AMD规范进行页面开发需要用到对应的库函数RequireJS,它采用异步方式加载模块,模块的加载不影响它后面语句的运行。所有依赖这个模块的语句,都定义在一个回调函数中,等到加载完成之后,这个回调函数才会运行。

1.3      CMD模块化规范

CMD即Common Module Definition通用模块定义,CMD规范是国内发展出来的,就像AMD有个requireJS,CMD有个浏览器的实现SeaJS,SeaJS要解决的问题和requireJS一样,只不过在模块定义方式和模块加载(可以说运行、解析)时机上有所不同。

二、Webpack基本介绍

2.1      Webpack介绍

Webpack是一个供浏览器环境使用的模块化打包工具,所有的静态资源都可以看成是一个个的小模块,模块之间可以相互依赖,而Webpack可以对这些依赖进行统一管理并打包发布,并将多种静态资源 js、css、less 转换成一个静态文件,减少了页面的请求,它做的事情是,分析你的项目结构,找到JavaScript模块以及其它的一些浏览器不能直接运行的拓展语言(Scss,TypeScript等),并将其打包为合适的格式以供浏览器使用。如下图所示:

基于webpack的前端开发环境搭建-LMLPHP

2.2      webpack的特点

1. 同时支持CommonJS和AMD模块,能够快速的迁移旧项目。

2. 串联式模块加载器及插件机制,具有更好的灵活性和扩展性,例如对CoffeeScript、ES 6的支持。

3. 可以基于配置或者智能分析打包成多个文件,实现分别满足公共模块和按需加载的需要,有效利用浏览器的缓存功能提升性能。

4. 将样式文件和图片等静态资源也可视为模块进行打包。配合loader加载器,可以支持sass,less等CSS预处理器,无须依靠grunt或gulp等构建工具,简化工程配置。

5. 开发时在内存中完成打包,性能更高,完全可以支持开发过程的实时打包需求。

6. 支持模块加载器和插件机制,可对模块灵活定制。特别是我最爱的babel-loader,有效支持ES6。

7. 内置有source map,即使打包在一起依旧方便调试。

三、Webpack在前端开发中的实际应用

3.1      基于webpack的前端开发环境搭建

1. 安装node.js,npm等工具,安装步骤不再一一说明

因为webpack基于commonJS的方式进行打包需要用到node.js的环境与npm包管理工具,用于管理与安装项目需要依赖的第三方库

2. 创建一个项目文件夹,并使用npm工具进行初始化

(1) 打开cmd执行npm init指令,用于初始化生成package.json文件

基于webpack的前端开发环境搭建-LMLPHP

(2) 安装webpack,在项目目录下执行如下的指令

npm install webpack  -g   表示全局安装

npm install webpack@版本号 --save-dev,使用--save-dev安装的插件,被写入到 devDependencies对象里面去,而使用--save安装的插件,则被写入到 dependencies 对象里面去。devDependencies里面的插件只用于开发环境,不用于生产环境,而dependencies是需要发布到生产环境的。

基于webpack的前端开发环境搭建-LMLPHP

(3) 这里直接采用webpack命令进行文件打包的方式不再讲解,直接使用创建webpack.config.js配置webpack打包信息的方式,简单配置说明如下:

webpack.config.js配置信息如下

var   path = require('path');  // 新版api要导入path包,用于获取文件绝对路径

module.exports={

    entry:'./src/page/index.js',   // 入口文件,需要打包的文件

    output:{

        // path:'./dist',   // 老版本的API

        path:path.resolve(__dirname,   'dist'),  // 新版本API

        filename:'[name].js'   // name表示根据输入的文件名称进行输出

    }

}

此处需要注意,如果安装的是新版本的webpack,此处如果直接用path:' '的话会报如下错误,需要path.resolve(__dirname,   'dist'),dist为打包后输出的总目录

Invalid   configuration object. Webpack has been initialised using a configuration   object that does not match the API schema.

 - configuration.output.path: The provided   value "./dist" is not an absolute path!

 -> The output directory as **absolute   path** (required).

(4) webpack公共模块抽取CommonsChunckPlugin插件的使用

主要作用:有一个A模块被B,C,D三个模块引用,这个时候A模块就可以放入到公共的模块中,在webpack配置文件中加入如下配置信息

plugins:   [

        new    webpack.optimize.CommonsChunkPlugin('common.js', ['index', 'login'])

]

参数common.js表示公共模块的文件名,后面的数组元素与entry一一对应,表示要提取这些模块中的公共模块

plugins:   [

        new    webpack.optimize.CommonsChunkPlugin(

            name:'commons',

            filename:'js/base.js')

]

(5) 安装和配置样式处理的loader

此种方式是js与css打包在一起,会出现样式延迟的现象,所以需要单独打包css并通过link的方式引入进来

2.   安装npm install   [email protected] --save-dev

(1)此时会出现如下问题:

UNMET   PEER DEPENDENCY

出现这个的时候,不要重新安装,只是提示我们当前不是最新版本,可以升级到最新版

(2)修改webpack.config.js

var   path = require('path');

var   webpack = require('webpack');

var   ExtractTextPlugin = require("extract-text-webpack-plugin");

module.exports={

    entry:{

          'common':['./src/page/common/index.js'],

          'index':['./src/page/index/index.js'],

        'login':['./src/page/login/index.js']

    },

    output:{

        // path:'./dist',

        path:path.resolve(__dirname, 'dist'),

        filename:'js/[name].js'

    },

    externals:{

        'jquery':'window.jQuery'

    },

    module: {

        loaders: [

            { test: /\.css/,   loader:ExtractTextPlugin.extract({

                fallback: 'style-loader',

                use: ['css-loader']})

            }

        ]

    },

    plugins: [

        new    webpack.optimize.CommonsChunkPlugin({

            name: 'common',

            filename:'js/base.js'}),

        new   ExtractTextPlugin("css/[name].css")

    ]

}

(3)这时候出现打包错误

71%   sealingF:\workspaceSet\vsc\blog-ng-tab\node_modules\webpack\lib\Chunk.js:34

throw   new Error("Chunk.entry was removed. Use hasRuntime()");

原因:extract-text-webpack-plugin官方针对webpack不同版本需要使用特定的版本

#   for webpack 3

npm   install --save-dev extract-text-webpack-plugin

#   for webpack 2

npm   install --save-dev [email protected]

#   for webpack 1

npm   install --save-dev [email protected]

解决方式:卸载之前的重新安装新的版本,卸载完毕需要看一下package.json中是否遗留了版本号,如果有先要删除

(6) 打包html的插件html-webpack-plugin

var   path = require('path');

var   webpack = require('webpack');

var   ExtractTextPlugin = require('extract-text-webpack-plugin');

var   htmlWebpackPlugin = require('html-webpack-plugin');

/**

 * 获取html-webpack-plugin参数的方法

 * @param name

 * @returns {{filename: string, template:   string, inject: boolean, hash: boolean, chunks: *[]}}

 */

var   getHtmlConfig=function (name) {

    return {

        filename:'view/'+name+'.html',

        // 也可以指定htmnpml的名称filename:'js/[name].js'

        template:'./src/view/'+name+'.html',

        // inject指定引入文件的位置是头部还是body内部

        inject:'body',

        hash:true,

        // 需要打包的模块,也就是需要将哪些js打包到对应的html中

          chunks:['common',name]

    }

};

var   config={

    entry:{

          'common':['./src/page/common/index.js'],

          'index':['./src/page/index/index.js'],

        'login':['./src/page/login/index.js']

    },

    output:{

        // path:'./dist',

        path:path.resolve(__dirname, 'dist'),

        filename:'js/[name].js'

    },

    externals:{

        'jquery':'window.jQuery'

    },

    module: {

        loaders: [

            { test: /\.css$/,   loader:ExtractTextPlugin.extract({

                fallback: 'style-loader',

                use: ['css-loader']})

            }

        ]

    },

    plugins: [

        // 独立通用模块到js/base.js

        new    webpack.optimize.CommonsChunkPlugin({

            name: 'common',

            filename:'js/base.js'}),

        // 打包css到单独的文件里

        new   ExtractTextPlugin("css/[name].css"),

        // html模板的处理

        new   htmlWebpackPlugin(getHtmlConfig('index')),

        new   htmlWebpackPlugin(getHtmlConfig('login'))

    ]

};

module.exports=config;

(7) 安装html-loader用于抽取公共的html模板

html-head.html文件(公共的html模板)

引入头部文件

(8) 图片及文字处理

加入如下的loader设置,安装url-loader,file-loader(当文件大于100的时候会以文件的形式打包,所以需要安装此模块)

{   test: /\.(gif|png|jpg|woff|svg|eot|ttf)\??.*$/,  // \??.*用于匹配带参数的图片

                loader:   'url-loader?limit=100&name=resource/[name].[ext]' }

至此,基本的webpack环境就已经搭建完毕了

四、总结

Webpack是一个自动化的前端构建工具,能够较大程度的提升前端开发效率及代码质量,让你在开发的时候能够以模块化的形式组织代码,而发布到生产环境中可以根据修改webpack的配置来实现依赖库的按需加载,代码压缩,less转换等等功能.

 

11-10 21:12