一、全面理解webpack
1、什么是 webpack?
webpack是近期最火的一款模块加载器兼打包工具,它能把各种资源,例如JS(含JSX)、coffee、样式(含less/sass)、图片等都作为模块来使用和处理,它能有Grunt或Gulp所有基本功能。webpack的官网是 https://webpack.github.io/ ,文档地址是https://webpack.github.io/docs,官网对webpack的定义是MODULE BUNDLER,他的目的就是把有依赖关系的各种文件打包成一系列的静态资源。 请看下图:
2、webpack 的优势
其优势主要可以归类为如下几个:
  1. webpack 是以 commonJS 的形式来书写脚本滴,但对 AMD/CMD 的支持也很全面,方便旧项目进行代码迁移。
  2. 支持很多模块加载器的调用,可以使模块加载器灵活定制,比如babel-loader加载器,该加载器能使我们使用ES6的语法来编写代码;less-loader加载器,可以将less编译成css文件;
  3. 开发便捷,能替代部分 grunt/gulp 的工作,比如打包、压缩混淆、图片转base64等。
  4. 可以通过配置打包成多个文件,有效的利用浏览器的缓存功能提升性能。
3、wepback它的目标是是什么?
webpack它能将依赖的模块转化成可以代表这些包的静态文件
  • 将依赖的模块分片化,并且按需加载
  • 解决大型项目初始化加载慢的问题
  • 每一个静态文件都可以看成一个模块
  • 可以整合第三方库
  • 能够在大型项目中运用
  • 可以自定义切割模块的方式

4、webpack较之其他类似工具有什么不同?

  • 有同步和异步两种不同的加载方式
  • Loader,加载器可以将其他资源整合到JS文件中,通过这种方式,可以讲所有的源文件形成一个模块
  • 优秀的语法分析能力,支持 CommonJs AMD 规范
  • 有丰富的开源插件库,可以根据自己的需求自定义webpack的配置

5、webpack为什么要将所有资源放在一个文件里面?

我们知道,对于浏览器来说,加载的资源越少,响应的速度也就越快,所以有时候我们为了优化浏览器的性能,会尽可能的将资源合并到一个主文件app.js里面。但是这导致的很大的缺点:

  • 当你的项目十分庞大的时候,不同的页面不能做到按需加载,而是将所有的资源一并加载,耗费时间长,性能降低。
  • 会导致依赖库之间关系的混乱,特别是大型项目时,会变得难以维护和跟踪。比如:哪些文件是需要A模块加载完后才能执行的?哪些页面会受到多个样式表同时影响的? 等许多问题。

而webpack可以很好的解决以上缺点,因为它是一个十分聪明的模块打包系统,当你正确配置后,它会比你想象中的更强大,更优秀。

二、开启wbpack之旅
安装步骤如下:

1、生成package.json文件;

先装好node和npm,因为webpack是一个基于node的项目。然后首先我们需要在根目录下生成package.json文件,需要进入项目文件内根目录下执行如下命令:npm init

如上通过一问一答的方式后会在根目录下生成package.json文件,如下所示:

2 . 通过全局安装webpack
执行命令如下:npm install -g webpack 如下所示:
在c盘下会生成node_modules文件夹中会包含webpack,此时此刻我们可以使用webpack命令了;
在常规项目中把webpack依赖加入到package.json

npm init npm install webpack --save

更详尽的安装方法个可以参考webpack安装
3. 配置webpack
每个目录下都必须有一个webpack.config.js,它的作用就好比Gulpfile.js、或者 Gruntfile.js,就是一个项目配置,告诉webpack需要做什么。
首先先贴上一个比较完整的webpack.config.js的代码,再详细介绍:
//详细的webpack.config.js结构分析:
var path = require('path');
var webpack = require('webpack');
var HtmlWebpackPlugin = require('html-webpack-plugin');
var TransferWebpackPlugin = require('transfer-webpack-plugin'); module.exports = {
    devtool: 'source-map',//由于打包后的代码是合并以后的代码,不利于排错和定位,只需要在config中添加,这样出错以后就会采用source-map的形式直接显示你出错代码的位置。
//noParse:[/jquery/],//表示跳过jquery,不对其进行编译,这样可以提高打包的速度
    //页面入口文件配置
    entry: {
page1: "./src/index.js",
//page2: ["./src/index.js", "./src/main.js"],支持数组形式,将加载数组中的所有模块,但以最后一个模块作为输出
    },
    //入口文件输出配置
    output: {
        path: "dist/js/page",
filename: "[name].bundle.js",// page1.bundle.js 和 page2.bundle.js,并存放到 ./dist/js/page 文件夹下。
publicPath: "/dist/" //网站运行时的访问路径。
    },
resolveLoader: {
//指定默认的loader路径,否则依赖走到上游会找不到loader
root: path.join(__dirname, 'node_modules'),
alias: {//给自己写的loader设置别名
"seajs-loader": path.resolve( __dirname, "./web_modules/seajs-loader.js" )
}
},
//新建一个开发服务器,并且当代码更新的时候自动刷新浏览器。
devServer: {
historyApiFallback: true,
noInfo: true,
hot: true,
inline: true,
progress: true,
port:9090 //端口你可以自定义
},
    module: {
        // module.loaders 是最关键的一块配置。它告知 webpack每一种文件都需要使用什么加载器来处理:
        loaders: [
{ test: /\.css$/, loader: 'style-loader!css-loader' },//.css 文件使用 style-loader 和 css-loader 来处理.
//{ test: /\.css$/, loader: 'style!css' },其他写法1、"-loader"其实是可以省略不写的,多个loader之间用“!”连接起来。
//{ test: /\.css$/, loaders: ["style", "css"] },其他写法2、用loaders数组形式;
//.scss 文件使用 style-loader、css-loader 和 sass-loader 来编译处理。
//在chrome中我们通过sourcemap可以直接调试less、sass源文件文件
{ test: /\.scss$/, loader: 'style!css!sass?sourceMap'},
{ test: /\.less$/, loader: 'style!css!less?sourceMap'},//.less 文件使用 style-loader、css-loader 和 less-loader 来编译处理
//.js 文件使用babel-loader来编译处理,设置exclude用来排除node_modules这个文件夹中的代码
{ test: /\.js$/, loader: 'babel!jsx',exclude: /node_modules/ }, 
{ test: /\.jsx$/, loader: "jsx-loader?harmony" },//.jsx 文件使用 jsx-loader 来编译处理
{ test: /\.json$/,loader: 'json'},
//{ test: /\.(png|jpg|jpeg|gif)$/, loader: 'url-loader?limit=8192'}, //图片文件使用 url-loader 来处理,小于8kb的直接转为base64
{test: /\.(png|jpg|gif|svg)$/,loader: 'url',
query: {limit: 10000,name: '[name].[ext]?[hash]'}//设置图片名称扩展名
},
{ test: /\.jade$/, loader: "jade-loader" },//.jade 文件使用 jade-loader 来编译处理
{ test: /\.ejs$/, loader: "ejs-loader" },//.ejs 文件使用 ejs-loader 来编译处理
{ test: /\.handlebars$/, loader: "handlebars-loader" },//.handlebars 文件使用handlebars-loader来编译处理handlebars模板文件
{ test: /\.dot$/, loader: "dot-loader" },//.dot 文件使用 dot-loader 来编译处理dot模板文件
{ test: /\.vue$/, loader: "vue-loader" },//.vue 文件使用 vue-loader 来编译处理
{ test: /\.coffee$/, loader: 'coffee-loader' },//.coffee 文件使用 coffee-loader 来编译处理
{ test: /\.html$/,loader: 'vue-html'},
{ test: /\.woff$/,loader: "url?limit=10000&minetype=application/font-woff"},
{ test: /\.ttf$/,loader: "file"},
{ test: /\.eot$/,loader: "file"},
{ test: /\.svg$/,loader: "file"}
        ]
    },
//分内置插件和外置插件
    plugins: [
//使用了一个 CommonsChunkPlugin 的插件,它用于提取多个入口文件的公共脚本部分,然后生成一个common.js来方便多页面之间进行复用。
new webpack.optimize.CommonsChunkPlugin('common.js'),
new webpack.optimize.UglifyJsPlugin({//压缩文件
compressor: {
warnings: false,//supresses warnings, usually from module minification
},
except: ['$super', '$', 'exports', 'require'] //排除关键字(可选)
}),
new webpack.DefinePlugin({// definePlugin 接收字符串插入到代码当中, 所以你需要的话可以写上 JS 的字符串
__DEV__: JSON.stringify(JSON.parse(process.env.BUILD_DEV || 'true')),
__PRERELEASE__: JSON.stringify(JSON.parse(process.env.BUILD_PRERELEASE || 'false'))
}),
new webpack.ProvidePlugin({//把一个全局变量插入到所有的代码中,支持jQuery plugin的使用;使用ProvidePlugin加载使用频率高的模块
//provide $, jQuery and window.jQuery to every script
$: "jquery",
jQuery: "jquery",
"window.jQuery": "jquery"
}),
new webpack.NoErrorsPlugin(), //允许错误不打断程序
new TransferWebpackPlugin([ //把指定文件夹下的文件复制到指定的目录
{from: 'www'}
], path.resolve(__dirname,"src")),
new HtmlwebpackPlugin({//用于生产符合要求的html文件;
title: 'Hello World app',
filename: 'assets/admin.html'
})
],
    //其它解决方案配置
    resolve: {
        root: 'E:/github/flux-example/src', //绝对路径, 查找module的话从这里开始查找(可选)
        extensions: ['', '.js', '.html', '.css', '.scss'], //自动扩展文件后缀名,意味着我们require模块可以省略不写后缀名
        alias: { //模块别名定义,方便后续直接引用别名,无须多写长长的地址//后续直接 require('AppStore') 即可
            AppStore : 'js/stores/AppStores.js',
            ActionType : 'js/actions/ActionType.js',
            AppAction : 'js/actions/AppAction.js'
        },
modulesDirectories: [//取相对路径,所以比起 root ,所以会多很多路径。查找module(可选)
'node_modules',
'bower_components',
'lib',
'src'
]
    } }; if (process.env.NODE_ENV === 'production') {
module.exports.devtool = '#source-map'
// http://vue-loader.vuejs.org/en/workflow/production.html
module.exports.plugins = (module.exports.plugins || []).concat([
new webpack.DefinePlugin({
'process.env': {
NODE_ENV: '"production"'
}
}),
new webpack.optimize.UglifyJsPlugin({
compress: {
warnings: false
}
}),
//为组件分配ID,通过这个插件webpack可以分析和优先考虑使用最多的模块,并为它们分配最小的ID
new webpack.optimize.OccurenceOrderPlugin()
])
}

plugins中包含很多的内置插件和外部插件,它们都有各自的功能,用来处理相关的文件,这里只是罗列了部分,具体用法请看webpack入门和实战(二):全面理解和运用plugins和loader

就像我在前面提到的,webpack.config.js的写法和在Node里的写法相同,我们主要看的就是文件中的module.exports里面的内容
  • entry 是指入口文件的配置项,它是一个数组的原因是webpack允许多个入口点。
  • output是指输出文件的配置项
    • path - 表示输出文件的路径
    • filename - 表示输出文件的文件名
  • plugins 顾名思义,使用插件可以给webpack添加更多的功能,使webpack更加的灵活和强大,webpack有两种类型的插件:

    • webpack内置的插件
// 首先要先安装webpack模块
var webpack = require("webpack");
module.exports = {
new webpack.optimize.UglifyJsPlugin({
compressor: {
warnings: false,
},
})
};
    • webpack外置插件
//npm install component-webpack-plugin 先要在安装该模版
var ComponentPlugin = require("component-webpack-plugin");
module.exports = {
plugins: [
new ComponentPlugin()
]
}

更多的插件以及插件的用法,大家可以到webpack的插件上查看。

  • module 配置处理文件的选项
    • loaders 一个含有wepback中能处理不同文件的加载器的数组
      • test 用来匹配相对应文件的正则表达式
      • loaders 告诉webpack要利用哪种加载器来处理test所匹配的文件
    • loaders 的安装方法
        $ npm install xxx-loader --save-dev
  • resolve:其它解决方案配置;
    • resolve.root,绝对路径, 查找module的话从这里开始查找(可选)
    • resolve.modulesDirectories,取相对路径,所以比起 root ,所以会多 parse 很多路径。查找module(可选)
    • resolve.extensions,自动扩展文件后缀名,意味着我们require模块可以省略不写后缀名
    • resolve.alias,模块别名定义,方便后续直接引用别名,无须多写长长的地址
三、利用webpack实现在页面上合理使用打包过后的js文件和图片
示例如下:
webpack_test目录结构如下:
最终完成版的目录结构为:
 index.html代码如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>demo1</title>
</head>
<body>
<div id="content"></div>
<img src="./build/img/demo.png">
<script src="./build/js/index.js"></script>
</body>
</html>

index.js代码如下:

require('./index.css');

index.css代码如下:

#content{
width:121px;
height:140px;
background-color: red;
}
demo.png自己随便找一张即可;
根据webpack.config.js的配置情况,操作步骤如下:
  • 全局安装webpack,npm install webpack -g
  • 进入到webpack_test目录下,初始化生成package.json文件,npm init
  • 需要安装的loader有css-loader、style-loader、url-loader,webpack, npm install css-loader style-loader url-loader webpack--save-dev
  • 执行webpack,生成打包过后的build/js/index.js,build/img/demo.png
  • 在index.html中引入即可

效果如下:

 源码地址为:http://download.csdn.net/detail/wdlhao/9612173,有需要的同学可以自行下载练习;
 四、理解webpack支持commonJS和AMD/CMD两种模块机制进行打包
 1.AMD/CMD模式:
     AMD 规范在这里:https://github.com/amdjs/amdjs-api/wiki/AMD,CMD 规范在这里:https://github.com/seajs/seajs/issues/242
  • AMD(Asynchronous Module Definition) 是 RequireJS 在推广过程中对模块定义的规范化产出。(即RequireJS模块规范)
RequireJS是一个工具库,主要用于客户端的模块管理。它可以让客户端的代码分成一个个模块,实现异步或动态加载,从而提高代码的性能和可维护性。它的模块管理遵守AMD规范(Asynchronous Module Definition)。RequireJS的基本思想是,通过define方法,将代码定义为模块;通过require方法,实现代码的模块加载。首先,将require.js嵌入网页,然后就能在网页中进行模块化编程了。<script data-main="scripts/main" src="scripts/require.js"></script>上面代码的data-main属性不可省略,用于指定主代码所在的脚本文件,在上例中为scripts子目录下的main.js文件。用户自定义的代码就放在这个main.js文件中。
  • CMD(Common Module Definition )是 SeaJS 在推广过程中对模块定义的规范化产出。(即SeaJS模块规范)
SeaJS是一个遵循CMD规范的JavaScript模块加载框架,可以实现JavaScript的模块化开发及加载机制。
  • CommonJS Modules/2.0 规范,是 BravoJS 在推广过程中对模块定义的规范化产出。
CommonJS API定义很多普通应用程序(主要指非浏览器的应用)使用的API,从而填补了这个空白。它的终极目标是提供一个类似Python,Ruby和Java标准库。这样的话,开发者可以使用CommonJS API编写应用程序,然后这些应用可以运行在不同的JavaScript解释器和不同的主机环境中。在兼容CommonJS的系统中,你可以实用JavaScript程序开发:
  • 服务器端JavaScript应用程序
  • 命令行工具
  • 图形界面应用程序
  • 混合应用程序(如,Titanium或Adobe AIR)

还有不少⋯⋯这些规范的目的都是为了 JavaScript 的模块化开发,特别是在浏览器端的。目前这些规范的实现都能达成浏览器端模块化开发的目的。

 2、AMD/CMD模式区别

2.1从官方推荐的写法上面得出:

CMD ----- 依赖就近

Js代码
//CMD
define(function(require,exports,module){
var a = require('./a');
a.doSomthing();
});

AMD ----- 依赖前置

Js代码
//AMD
define(['./a','./b'],function(a,b){
//......
a.doSomthing();
//......
b.doSomthing();
})

当然AMD也支持CMD的写法。

2.2、执行顺序上:

    • CMD是延迟执行,推崇的是as lazy as possible
    • AMD是提前执行,requireJS从2.0开始可以延迟执行
2.3、api设计角度:
    • CMD的API推崇职责单一,没有全局的require
    • AMD的API默认是一个当多个用:比如require有全局的和局部的
 

webpack入门和实战(一):webpack配置及技巧的更多相关文章

  1. webpack入门(四)——webpack loader 和plugin

    什么是loader loaders是你用在app源码上的转换元件.他们是用node.js运行的,把源文件作为参数,返回新的资源的函数. 例如,你可以用loaders告诉webpack加载 coffee ...

  2. 微信小程序入门与实战 常用组件API开发技巧项目实战*全

    第1章 什么是微信小程序? 第2章 小程序环境搭建与开发工具介绍 第3章 从一个简单的“欢迎“页面开始小程序之旅 第4章 第二个页面:新闻阅读列表 第5章 小程序的模板化与模块化 第6章 构建新闻详情 ...

  3. webpack入门和实战(二):全面理解和运用loader和plugins

    您的阅读目录: 一.理解webpack加载器loader 二.理解less-loader加载器的使用 三.理解babel-loader加载器的使用 四.webpack命令行常见使用的操作 五.用web ...

  4. webpack入门指南(基于webpack v4.41.2)

    2019年12月5日初稿,目前webpack已经更新到v4.41.2,本文正是基于该版本,在windows8.1操作系统下进行的demo编译,适用于想入门webpack的前端开发人员. webpack ...

  5. webpack入门教程之Hello webpack(一)

    webpack入门教程系列为官网Tutorials的个人译文,旨在给予想要学习webpack的小伙伴一个另外的途径.如有不当之处,请大家指出. 看完入门教程系列后,你将会学习到如下内容: 1.如何安装 ...

  6. webpack入门(三)webpack的api

    终于到了webpack api这一篇,我都等不及了0.0; webpack is fed a configuration object. Depending on your usage of webp ...

  7. nginx入门与实战 安装 启动 配置nginx Nginx状态信息(status)配置 正向代理 反向代理 nginx语法之location详解

    nginx入门与实战 网站服务 想必我们大多数人都是通过访问网站而开始接触互联网的吧.我们平时访问的网站服务 就是 Web 网络服务,一般是指允许用户通过浏览器访问到互联网中各种资源的服务. Web ...

  8. webpack入门(五)webpack CLI

    webpack的CLI安装和命令 Installation $ npm install webpack -g The webpack command is now available globally ...

  9. webpack入门(四)webpack的api 2 module

    接着介绍webpack的module. module Options affecting the normal modules (NormalModuleFactory)  这些选项影响普通的模块 m ...

随机推荐

  1. 一篇文看懂Hadoop:风雨十年,未来何去何从

    本文分为技术篇.产业篇.应用篇.展望篇四部分 技术篇 2006年项目成立的一开始,“Hadoop”这个单词只代表了两个组件——HDFS和MapReduce.到现在的10个年头,这个单词代表的是“核心” ...

  2. Ajax实现定时刷新页面

    function deleteValue(){ var refresh = function() { $.ajax({   type:'post',   url:'/Application/index ...

  3. c#获取当前应用程序所在路径

    一.获取当前文件的路径1.   System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName     获取模块的完整路径,包括文 ...

  4. MVC之前的那点事儿系列(5):Http Pipeline详细分析(下)

    文章内容 接上面的章节,我们这篇要讲解的是Pipeline是执行的各种事件,我们知道,在自定义的HttpModule的Init方法里,我们可以添加自己的事件,比如如下代码: public class ...

  5. Csharp: Create Excel Workbook or word from a Template File using aspose.Word 14.5 and aspose.Cell 8.1

    winform: /// <summary> /// /// </summary> /// <param name="sender"></ ...

  6. Calling startActivity() from outside of an Activity

    在Activity中使用startActivity()方法不会有任何限制,因为Activity重载了Context的startActivity()方法.但是如果是在其他地方(如Widget或Servi ...

  7. WinForm 窗体应用程序 (初步)之二

    现在,我们来了解一些基本控件.控件是放置在工具箱里的,你可以在界面的左侧或者通过菜单栏的视图选项找到它. (1)Label 控件 这是一个用于放置文字的控件,因为你不能在窗体上直接输入文字. (2)T ...

  8. Slick – 这是你需要的最后一款 jQuery 传送带插件

    slick 是一款完全响应式的 jQuery 传送带插件,能够根据容器自动适应宽度.在现代浏览器中会使用 CSS3 来实现特殊效果,可以使用扩展方法对项目进行添加.删除和过滤.这是你需要的最后一款 j ...

  9. 在线代码编辑器CodeMirror简介

    1.什么是Code Mirror 最近做一个项目需要在网页上实现一个代码编辑器,支持语法高亮.自动缩进.智能提示等功能.发现Code Mirror刚好满足所有需求.Code Mirror是由js写的一 ...

  10. 颜色渐变的JS代码

    今天做组织机构,要分级别显示颜色,自己计算半天也没算出颜色渐变的方法,出来总是花里胡哨的难看的不要不要的,所以查了一下,找到一个js代码,试了试,很完美哦! <!DOCTYPE html> ...