详解前端模块化工具-webpack

简介:

webpack是一个module bundler,抛开博大精深的汉字问题,我们暂且管他叫'模块管理工具 '。随着js能做的事情越来越多,浏览器、服务器,js似乎无处不在,这时,使日渐增多的js代码变得合理有序就显得尤为必要,也应运而生了很多模块化工 具。从服务器端到浏览器端,从原生的没有模块系统的`<script>`到基于Commonjs和AMD规范的实现到ES6 modules。为了模块化和更好的模块化,我们总是走在探索的路上。

但是这些实现模块化的方法或多或少都有他们的缺点。比如说使用`<script>`标签导入js模块,顺序不好把握且我们需要自己梳理 可能的冲突和依赖;使用Commonjs规范来解决问题,它使我们在服务器端的模块得到了重用,但是在浏览器端,网络的请求都是异步的,无法并行的 require多个module。ES6 modules的实现也只是一小部分,并且想要得到所有浏览器的支持,相比还是需要相当的一段时间。

当然灵活的模块管理只是webpack的众多特性之一,它还有众多优秀的特性:

 
 
  1. - 它同时支持commonjs和AMD规范(甚至混合的形式); 
  2. - 它可以打成一个完整的包,也可以分成多个部分,在运行时异步加载(可以减少第一次加载的时间); 
  3. - 依赖在编译时即处理完毕,可以减少运行时包的大小; 
  4. - Loaders可以使文件在编译时得到预处理,这可以帮我们做很多事情,比如说模板的预编译,图片的base64处理; 
  5. - 丰富的和可扩展的插件可以适应多变的需求。 

一、webpack详解

最近在学习ES6和React相关的知识,为了更加方便自己写代码,给自己写了个脚手架generator-reactpack。生成的项目中可以看到一个基本的webpack.config.js文件:

 
 
  1. var webpack = require('webpack'); 
  2. module.exports = { 
  3.     entry: [ 
  4.         'webpack/hot/only-dev-server'
  5.         './js/app.js' 
  6.     ], 
  7.     output: { 
  8.         path: './build'
  9.         filename: 'bundle.js' 
  10.     }, 
  11.     module: { 
  12.         loaders: [ 
  13.         { test: /\.js?$/, loaders: ['react-hot''babel'], exclude:     /node_modules/ }, 
  14.         { test: /\.js$/, exclude: /node_modules/, loader: 'babel-loader'}, 
  15.         { test: /\.css$/, loader: "style!css" }, 
  16.         {test: /\.less/,loader: 'style-loader!css-loader!less-loader'
  17.         ] 
  18.     }, 
  19.     resolve:{ 
  20.         extensions:['','.js','.json'
  21.     }, 
  22.     plugins: [ 
  23.         new webpack.NoErrorsPlugin() 
  24.     ] 
  25. }; 

webpack.config.js文件通常放在项目的根目录中,它本身也是一个标准的Commonjs规范的模块。在导出的配置对象中有几个关键的参数:

1.entry

entry可以是个字符串或数组或者是对象。

当entry是个字符串的时候,用来定义入口文件:

1 entry: './js/main.js'

当entry是个数组的时候,里面同样包含入口js文件,另外一个参数可以是用来配置webpack提供的一个静态资源服务器,webpack- dev-server。webpack-dev-server会监控项目中每一个文件的变化,实时的进行构建,并且自动刷新页面:

1 entry: [
2     'webpack/hot/only-dev-server',
3     './js/app.js'
4 ]

当entry是个对象的时候,我们可以将不同的文件构建成不同的文件,按需使用,比如在我的hello页面中只要\<script src='build/Profile.js'></script>引入hello.js即可:

1 entry: {
2     hello: './js/hello.js',
3     form: './js/form.js'
4 }

2.output

output参数是个对象,用于定义构建后的文件的输出。其中包含path和filename:

1 output: {
2     path: './build',
3     filename: 'bundle.js'
4 }

当我们在entry中定义构建多个文件时,filename可以对应的更改为[name].js用于定义不同文件构建后的名字。

3.module

关于模块的加载相关,我们就定义在module.loaders中。这里通过正则表达式去匹配不同后缀的文件名,然后给它们定义不同的加载器。比如说给less文件定义串联的三个加载器(!用来定义级联关系):

 
 
  1. module: { 
  2.     loaders: [ 
  3.         { test: /\.js?$/, loaders: ['react-hot''babel'], exclude: /node_modules/ }, 
  4.         { test: /\.js$/, exclude: /node_modules/, loader: 'babel-loader'}, 
  5.         { test: /\.css$/, loader: "style!css" }, 
  6.         { test: /\.less/, loader: 'style-loader!css-loader!less-loader'
  7.     ] 

此外,还可以添加用来定义png、jpg这样的图片资源在小于10k时自动处理为base64图片的加载器:

1 { test: /\.(png|jpg)$/,loader: 'url-loader?limit=10000'}

给css和less还有图片添加了loader之后,我们不仅可以像在node中那样require js文件了,我们还可以require css、less甚至图片文件:

1 require('./bootstrap.css');
2 require('./myapp.less');
3 var img = document.createElement('img');
4 img.src = require('./glyph.png');

但是需要知道的是,这样require来的文件会内联到 js bundle中。如果我们需要把保留require的写法又想把css文件单独拿出来,可以使用下面提到的[extract-text-webpack-plugin]插件。

在 上面示例代码中配置的第一个loaders我们可以看到一个叫做react-hot的加载器。我的项目是用来学习react写相关代码的,所以配置了一个 react-hot加载器,通过它,可以实现对react组件的热替换。我们已经在entry参数中配置了`webpack/hot/only-dev- server`,所以我们只要在启动webpack开发服务器时开启--hot参数,就可以使用react-hot-loader了。在 package.json文件中这样定义:

1 "scripts": { 2 "start": "webpack-dev-server --hot --progress --colors", 3 "build": "webpack --progress --colors" 4 }

4.resolve

webpack在构建包的时候会按目录的进行文件的查找,resolve属性中的extensions数组中用于配置程序可以自行补全哪些文件后缀:

1 resolve:{
2     extensions:['','.js','.json']
3 }

然后我们想要加载一个js文件时,只要require('common')就可以加载common.js文件了。
5.plugin

webpack提供了[丰富的组件]用来满足不同的需求,当然我们也可以自行实现一个组件来满足自己的需求。在我的项目里面没有特殊的需求,于是便只是配置了NoErrorsPlugin插件,用来跳过编译时出错的代码并记录,使编译后运行时的包不会发生错误:

1 plugins: [
2     new webpack.NoErrorsPlugin()
3 ]

6.externals

当我们想在项目中require一些其他的类库或者API,而又不想让这些类库的源码被构建到运行时文件中,这在实际开发中很有必要。此时我们就可以通过配置externals参数来解决这个问题:

1 externals: {
2 "jquery": "jQuery" 3 }

这样我们就可以放心的在项目中使用这些API了:var jQuery = require("jquery");

7.context

当我们在require一个模块的时候,如果在require中包含变量,像这样:

1 require("./mods/" + name + ".js");

那么在编译的时候我们是不能知道具体的模块的。但这个时候,webpack也会为我们做些分析工作:

1.分析目录:'./mods';
2.提取正则表达式:'/^.*\.js$/';

于是这个时候为了更好地配合wenpack进行编译,我们可以给它指明路径,像在cake-webpack-config中所做的那样(我们在这里先忽略abcoption的作用):

1 var currentBase = process.cwd();
2 var context = abcOptions.options.context ? abcOptions.options.context :
3 path.isAbsolute(entryDir) ? entryDir : path.join(currentBase, entryDir);

二、why webpack?

webpack与gulp并不矛盾,甚至一起使用会得到最大化的利益,webpack与gulp。使用webpack进行assets编译,使用gulp进行打包似乎就是为了让它们各司其职,用其所长。

关于工具的定位

webpack的定位是module bundler,作为模块化工具,它的竞争对手看起来更像是[browserify],而不是[Gulp],基于流的自动化构建工具。然而事实也是这样的。  

功能和使用方式上的不同

webpack提供了一些非常实用的功能,像在前面我们体会到的那些,比如说图片的处理,resolve的处理,分开构建[webpack-code-splitting]等等 。 许多其他工具需要插件的功能,webpack只要配置一下就可以了。

有时候一个东西到底怎样,自己折腾一遍或许体会就更加深刻了。

三、拓展阅读

- [webpack]
- [cake-webpack-config]
- [webpack-howto]
- [webpack-compared]


作者:大额_skylar

来源:51CTO

相关文章
|
20天前
|
前端开发 开发者
在前端开发中,webpack 作为一个强大的模块打包工具,为我们提供了丰富的功能和扩展性
【9月更文挑战第1天】在前端开发中,Webpack 作为强大的模块打包工具,提供了丰富的功能和扩展性。本文重点介绍 DefinePlugin 插件,详细探讨其原理、功能及实际应用。DefinePlugin 可在编译过程中动态定义全局变量,适用于环境变量配置、动态加载资源、接口地址配置等场景,有助于提升代码质量和开发效率。通过具体配置示例和注意事项,帮助开发者更好地利用此插件优化项目。
48 13
|
30天前
|
JavaScript IDE 前端开发
前端开发工具配置 nodejs & git & IDE
前端开发工具配置 nodejs & git & IDE
|
1月前
|
前端开发 JavaScript C++
【绝技大公开】Webpack VS Rollup:一场前端工程化领域的巅峰对决,谁能笑到最后?——揭秘两大构建神器背后的秘密与奇迹!
【8月更文挑战第12天】随着前端技术的发展,模块化与自动化构建成为标准实践。Webpack与Rollup作为主流构建工具,各具特色。Webpack是一款全能型打包器,能处理多种静态资源,配置灵活,适合复杂项目;Rollup专注于ES6模块打包,利用Tree Shaking技术减少冗余,生成更精简的代码。Rollup构建速度快,配置简洁,而Webpack则拥有更丰富的插件生态系统。选择合适的工具需根据项目需求和个人偏好决定。两者都能有效提升前端工程化水平,助力高质量应用开发。
22 1
|
21天前
|
JavaScript 前端开发 API
解锁前端开发新境界:Vue.js携手Webpack,打造高效构建流程,你的项目值得拥有!
【8月更文挑战第30天】随着前端技术的发展,模块化与组件化趋势愈发显著。Vue.js 以其简洁的 API 和灵活的组件系统,深受开发者喜爱;Webpack 则凭借强大的模块打包能力成为前端工程化的基石。两者结合,不仅简化了组件编写与引用,还通过模块热替换、代码分割等功能大幅提升开发效率。本文将通过具体示例,展示如何利用 Vue.js 和 Webpack 构建高效、有序的前端开发环境。从安装配置到实际应用,逐步解析这一组合的优势所在。
34 0
|
1月前
|
JavaScript 前端开发
什么是前端构建工具?vite和vite脚手架的关系!
【8月更文挑战第1天】前端构建工具简析
52 4
|
1月前
|
前端开发 JavaScript
前端必会的JavaScript模块化
【8月更文挑战第3天】JavaScript模块化
20 1
|
1月前
|
开发框架 前端开发 JavaScript
基于SqlSugar的开发框架循序渐进介绍(18)-- 基于代码生成工具Database2Sharp,快速生成Vue3+TypeScript的前端界面和Winform端界面
基于SqlSugar的开发框架循序渐进介绍(18)-- 基于代码生成工具Database2Sharp,快速生成Vue3+TypeScript的前端界面和Winform端界面
|
1月前
|
前端开发 开发者
在前端开发中,webpack 作为模块打包工具,其 DefinePlugin 插件可在编译时动态定义全局变量,支持环境变量定义、配置参数动态化及条件编译等功能。
在前端开发中,webpack 作为模块打包工具,其 DefinePlugin 插件可在编译时动态定义全局变量,支持环境变量定义、配置参数动态化及条件编译等功能。本文阐述 DefinePlugin 的原理、用法及案例,包括安装配置、具体示例(如动态加载资源、配置接口地址)和注意事项,帮助开发者更好地利用此插件优化项目。
43 0
|
1月前
|
开发框架 前端开发 API
使用代码生成工具快速开发应用-结合后端Web API提供接口和前端页面快速生成,实现通用的业务编码规则管理
使用代码生成工具快速开发应用-结合后端Web API提供接口和前端页面快速生成,实现通用的业务编码规则管理
|
7天前
|
SpringCloudAlibaba JavaScript 前端开发
谷粒商城笔记+踩坑(2)——分布式组件、前端基础,nacos+feign+gateway+ES6+vue脚手架
分布式组件、nacos注册配置中心、openfegin远程调用、网关gateway、ES6脚本语言规范、vue、elementUI
谷粒商城笔记+踩坑(2)——分布式组件、前端基础,nacos+feign+gateway+ES6+vue脚手架