手把手带你入门webpack

本文是在windows系统下使用webpack,其他系统只有命令行工具使用方式有区别,您可放心食用。

1 什么是webpack

webpack是一个前端开发打包工具。

它打包的是什么

通下面这张图片可以看出,webpack可以将我们开发项目时编写的多个不同类型的模块依赖文件(其实就是我们写的各个代码文件),打包成为几个静态资源文件(用来在浏览器上运行)

image.png

为什么要使用webpack

如果你现在只是在简单地学习html/css/js,那么你就不会体会到webpack对你是否有用,如果你已经具备了一些前端基础,准备做一个完整项目练练手,那么使用webpack吧,他就像你的总管,帮你自动处理各种你本来需要亲自动手的事情,比如es6转换为es5(现在大多浏览器对还不能es6很好的支持,所以要借用babel相关工具进行转换我们编写的es6代码)。

让我们开启webpack之旅吧

安装webpack

推荐使用npm安装webpack

npm是node.js的一个包管理工具,需要先安装node.js才能使用(安装教程请自行百度)。安装完node.js后,新建一个文件夹project,我们的项目就在该文件夹下面建立,project文件夹就是我们项目的根目录。

在项目根目录新建模板文件index.html(模板文件是开始学前端的时候写的那个html文件,只不过这里有更丰富的意义,这是后话,暂且不表)

在安装webpack之前,我们先在项目根目录下面新建一个package.json文件配合webpack使用,这是一个npm安装包的说明文件。我们使用命令行工具cmd,进入我们的项目根目录,自动创建package.json文件.

npm init

一路回车下去,知道最后输入y确认即可。

接下来我们安装webpack,还是在项目根目录下

npm install webpack -g   或者
npm install webpack --save  或者
npm install webpack --save-dev

-g 表示全局安装

--save 和 --save-dev 表示安装到你的项目根目录,--save 会把依赖包名称添加到 package.json 文件的 dependencies 下,--save-dev 则添加到 package.json 文件的 devDependencies 下。dependencies是运行时依赖,devDependencies是开发时的依赖。运行时需要用到的包使用--save,否则使用--save-dev,如果你还是不知道使用哪个,使用--save即可,以后安装的包同理。

配置webpack

在package.json中对scripts对象进行相关设置

"scripts": {
    "start": "webpack" // 修改的是这里,使用npm start 启动打包命令,直接用webpack命令也是一样的
  },

如果想要在运行webpack的时候,使用一些webpack的参数,可以在package.json 文件中配置

"scripts":{"webpack": "webpack --config webpack.config.js --progress看到打包过程  --display-modules看到打包了哪些模块" --color彩色字体  --display-reason打看到包原因}

在项目根目录下面创建webpack配置文件webpack.config.js

//基本结构
module.exports = {
var path = require('path');
  context: path.join(__dirname),  //这是entry配置项的根目录(绝对路径)
    entry: "./src/root.js",//打包入口文件,就是打包谁
    output: {
        path: __dirname + "/dist/",//打包后文件放置的目录路径
        // publicPath: "发布项目时在相对路径前面添加的绝对路径"
        filename: "bundle.js"//打包后文件的名字
    }
}

context是运行webpack打包程序时的上下文环境(项目根目录),__dirname(注意是两个下划线)是node.js的一个全局环境变量。

entry:

写法一:字符串 ----------打包一个入口文件,如上

写法二: 数组 ------------['./a.js', './b.js'] 打包两个不相依赖的文件,打包在一起

写法三:对象----------在多页面应用中,针对不同的页面填写不同的入口文件

entry: {
    page1:  './a.js',-----可以是一个
    page2: ['./as.js', './b.js']-------可以是多个
}

此时如果还像上面那样子写output则只会生成一个输出文件,且后面的打包文件会把前面输出文件覆盖,解决方法是在filename中添加一个占位符,区分不同输出文件,方法有三种:

1 [name] 就是entry对象的key值,page1, page2

output: {
filename: '[name]'.js,
path: __dirname + 'src'
}

2 [hash] 每次打包生成的一个hash值,假设为“123asd”,可以和[name]一起使用

output: {
filename: '[name]-[hash]'.js,
path: __dirname + 'src'
}

多个打包生成文件hash相同,都是“123asd”

3 [chunkhash] 每一个chunk自己的hash值----打包时可以看到chunk(模块),多个打包生成文件hash不同,可以和其他两个结合使用。

那么问题来了,因为我们使用了hash值来编码打包后生成的文件,而我们的html文件引用这个js文件时就必须保持同名,所以每次打包都需要手动更改引用文件的名字,相当麻烦。

我们可以使用一个插件来自动帮助我们引用打包后的js文件。

webpack插件 html-webpack-plugin

官网:https://www.npmjs.com/package/html-webpack-plugin

先利用npm安装

npm install html-webpack-plugin --save-dev

然后在webpack.config.js文件中引用

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

在 export.modules = {}中填写

plugins: [
    new htmlWebpackPlugin({----------初始化插件
    template: 'index.html'-------模板文件(插件作用下生成文件的模板),注意这个路径就是当下目录,因为webpack中有一个运行上下文(context),即webpack的运行所在目录,而index.html在当下目录,所以路径这样写没问题
    })
]

新生成的这个index.hml的所在目录也是output的路径下的目录

output: {
    filename: 'js/[name]'.js,
    path: __dirname + '/dist/'
}

一个index.htm文件会生成在dist目录下,里面有对[name]'.js的引用,[name]'.js会生成在./dist/js/目录下

还可以增加另外一些参数

plugins: [
    new htmlWebpackPlugin({
    template: 'index.html',
    filename: 'index-[hash].html',   //也可以指定生成的文件的名字,
    inject: 'head'    //指定打包生成的js是在head标签中引用,不强制要求,用false   
    minify: {---------对项目进行压缩操作
        removeComments: true,--------删除注释
        collapseWhitespace: true----------删除空格
    }
    })
]

此时我们根目录下的index.html就不需要填写打包出来的js的引用了

如果有多个页面,同样可以使用这个插件做到,只需要在plugins:[]数组中新增加一向即可,同时利用chunks:[ 'entry的key值' ]参数决定这个文件时要引入哪个入口文件的打包:

entry: {
    main: './src/main.js',
    a: './src/main.js',
    b: './src/main.js',
    c: './src/main.js'
}

plugins: [
    new htmlWebpackPlugin({
        template: 'index.html',
        filename: 'a.html', 
        inject: 'body' ,
        chunks: ['main', 'a']   
    }),

    new htmlWebpackPlugin({
        template: 'index.html',
        filename: 'b.html', 
        inject: 'body' ,
        chunks: [ 'b']   或者  excludeChunks: ['main', 'a', 'c']表示加载排除哪些chunk之外的chunk
    }),

    new htmlWebpackPlugin({
        template: 'index.html',
        filename: 'c.html', 
        inject: 'body' ,
        chunks: [ 'c']  
    }),
    
]

到现在webpack的基本配置也就完成了,当然,如果你的项目没有那么复杂,只是用来练手,可以忽略htmlWebpackPlugin这个插件,一样可以完美的使用webpack.

webpack应用之loaders

你会发现,仅仅只有前面的工作,webpack好像并没有多少卵用,反而增加了很多开发工作,想要解开这个困惑,请耐心看下去。

我们说过,webpack是一个管家,既然如此,我们就开始给它安排任务了,正是这些任务的下放,才让我们开发工作如释重负。

什么是loaders

先看官网的定义:
Loaders allow you to preprocess files as you require() or “load” them. Loaders are kind of like “tasks” in other build tools, and provide a powerful way to handle frontend build steps. Loaders can transform files from a different language like, CoffeeScript to JavaScript, or inline images as data URLs. Loaders even allow you to do things like require() css files right in your JavaScript!

大体意思就是,loaders能够帮我们做一些预处理,将不同语言编写的文件处理成能正常使用的样子。

不同的loader具有不用的功能,都需要先安装,推荐使用npm安装。

我们先在这里将两个重要的loader的使用,以起到提纲挈领的作用,更多loader使用将在以后更新。

利用webpack构建本地服务器

webpack-dev-server

在项目根目录安装,就是在cmd命令下利用cd命令,进入我们创建的project文件夹

npm install --save-dev webpack-dev-server

配置

在webpack.config.js的module.exports = {}里面添加下面一项

    devServer: {
        contentBase: "./",//本地服务器所加载的页面所在的目录,即当前project目录
        historyApiFallback: true,//不跳转
        inline: true//实时刷新
    },

在package.json中配置

"scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "start": "webpack",
    "server": "webpack-dev-server --inline --content-base --open"
  },

实现修改代码时,页面时时更新。

启动本地服务器,默认是8080端口,cmd进入project文件夹下,运行以下命令

npm run server

注意: 进入项目的根目录运行npm run server,webpack配置文件中本地服务器所加载的页面所在的目contentBase的值应该是从这里开始,比如要加载的文件在项目根目录,那么contentBase: "./"

修改源代码,页面不能实时更新的问题

我们修改我们的源文件后,自动打包生成的bundle.js其实只是一个虚拟的文件,本地其实是没有打包编译的,所以我们不能使用本地路径去引用,在引用打包生成文件bundle.js的时候,将路径改为绝对地址

src="http://localhost:8080/dist/bundle.js",即可

如果你还是没有解决这个问题,打开你的webpack配置文件webpack.config.js,

将publicPath添加进文件输出

output: {
    path: __dirname + "/dist/",
    publicPath: "/dist/",
    filename: "bundle.js"
},

如果问题还没解决,看一下你的webstorm编辑器的设置,参考

https://www.cnblogs.com/wshiqtb/p/5924172.html

补充

npm run server表示运行package.json中"scripts"中的server命令

package.json文件中output的路径:

path----表示你打包后生成的打包文件放在你的电脑的那个目录下

publicPath----表示服务器引用资源的路径(相对于服务器根目录)

webapck对图片的处理

url-loader 或者 file-loader

npm安装方法和前面一样,安装哪一个可以看了下面的介绍自行决定

在模板文件和css文件中引用图片写相对地址,在react组件中引用图片用相对地址找不到图片,可以用绝对地址,从根目录往下写路径,也可以用node的方法

<img src="${ require('相对路径') }">

在webpack.config.js的module.exports = {}里面添加下面一项

{
    test: /\.(png|jpg|gif|svg)$/i,
    loader: 'file-loader',
    query: {
        name: 'assets/[name]-[hash:5].[ext]'//打包后的图片放在assets文件夹下,图片名字为 他的,名字+一个5位的hash值,后缀名为ext
    }
}

webpack2貌似不支持query,可以直接用loader: 'url-loader?limit=8192&name=img/[name]-[hash].[ext]'这种写法。

另一个处理图片的loader
loader: 'url-loader?limit=8192'

当文件大于limit值(bytes)的时候交给file-loader处理,当文件小于这个值时候,图片被转换成一串base64的编码,直接插入引用图片的文件,使之变大,但是却不用通过http请求单独去请求这张图片资源

有一个loader可以用于压缩图片: image-webpack-------不要忘了先安装

如果和url-loader写在一起,可以这样写:

test: /.(png|jpg|gif|svg)$/i,
loaders: [
'url-loader?limit=8192&name=assets/[name]-[hash:5].[ext]',
'image-loader'
]----------注意loader中如果有多个参数时,处理顺序是从右向左

上面就是两个比较容易出错的loader的使用,更多loader的使用,请参考“入门Webpack,看这篇就够了http://www.jianshu.com/p/42e11515c10f

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,590评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 86,808评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,151评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,779评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,773评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,656评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,022评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,678评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,038评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,659评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,756评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,411评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,005评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,973评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,053评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,495评论 2 343