webpack 是一个现代 JavaScript 应用程序的静态模块打包器(module bundler)。

当 webpack 处理应用程序时,它会递归地构建一个依赖关系图(dependency graph),其中包含应用程序需要的每个模块,然后将所有这些模块打包成一个或多个 bundle。

基本安装

  1. 局部安装,官方也是推荐安装到项目目录下
mkdir webpack-demo-1
cd webpack-demo-1
npm init -y //生成package.json,并且一路同意,如果没啥个性化的内容则省了你一路狂按enter
npm install --save-dev webpack //安装到开发环境里面(devDependicies)
  1. webpack基本配置文件
touch webpack.config.js
vi webpack.config.js

配置文件内容如下

const path = require('path');

module.exports = {
entry: './src/index.js', // 这里应用程序开始执行,webpack 开始打包
output: {
// webpack 如何输出结果的相关选项
  filename: 'bundle.js',//输出资源块的名字(asset chunk)
  path: path.resolve(__dirname, 'dist') // 所有输出文件的目标路径,我的就是./dist/bundle.js
}
};

把当前目录的src下的index.js打包到了dist目录下,并且生成了(emmited)一个改头换面的bundle.js,里面的代码面目全非啊。

可以有多个入口(entry)

entry: {
scss: './src/css/main.scss', //对象的键名scss 就是输出文件的name
bundle: './src/js/app.js'
}, output: {
filename: "[name].js",
path: path.resolve(__dirname, 'dist/js')
// publicPath: "/output/"
},

多个入口最好写成对象的形式,官网说如果写成了数组,输出的内容会是数组的第一个。

上述代码会在dist/js目录下生成scss.js和bundle.js

path

其中,配置文件的第一行代码使用了Node的内置模块path,并且在它前面加上 __dirname这个全局变量(也就是第七行代码)。可以防止不同操作系统之间的文件路径问题,并且可以使相对路径按照预期工作。
即使你的index.js内容为空,bundle.js里面也有一些基本的打包代码。

  1. 基本的使用
//第一种方法,使用当前目录的node_modules里面的webpack
./node_modules/.bin/webpack
//第二种方法使用npm脚本
//首先在你的package.json里面添加下列代码
{
...
"scripts": {
"build": "webpack"
},
...
}
//然后,使用下列代码即可
npm run bulid
//第三种方法,高版本的npm自带了npx
npx webpack //npx会自动查找当前依赖包中的可执行文件,如果找不到,就会去 PATH 里找。如果依然找不到,就会帮你安装!

所以说呢,我选择了第三种使用方法。

babel-loader

ES6或其他版本js转换成通用js代码,毫无疑问应该使用babel,不过在webpack的世界里面统一使用loader,所以我们google webpack babel-loader
loader 可以将所有类型的文件转换为 webpack 能够处理的有效模块,然后你就可以利用 webpack 的打包能力,对它们进行处理。

有个坑,很容易搞错的坑

babel-loader不同版本的安装脚本、配置文件是不同的……

(@ο@) 哇~你搜出的最新的文档用这么小的文字告诉你,你用webpack 3.x babel-loader 7.x | babel 6.x的去这个链接,webpack 3.x | babel-loader 8.x | babel 7.x的去当前的这链接链接
好吧,我用上一版本的吧。
所以我的安装脚本是

npm install --save-dev babel-loader babel-core babel-preset-env webpack

配置文件是

//依然属于webpack.config.js配置的一部分,
module: {
 //这是关于模块的配置
rules: [
   //模块规则(配置 loader、解析器等选项)
{
    test: /\.js$/, //使用正则判断后缀是js的文件
    exclude: /(node_modules|bower_components)/,
    //除了这两目录下的node_modules|bower_components
use: {
      loader: 'babel-loader', //用这个loader处理.js的文件
      options: {
        presets: ['env'] //选项,还记得单独使用babel的时候建立的那个.babelrc嘛,就是那个作用。
      }
}
}
]
}

借此可以得到loader的两个作用:

  1. 识别出应该被对应的 loader 进行转换的那些文件。(使用 test 属性)
  2. 转换这些文件,从而使其能够被添加到依赖中(并且最终添加到 bundle 中)(use 属性)
    ./src/js/module-1.js、module-2.js、app.js三个文件,都是新的语法,用的模块化写法,有的浏览器不支持,所以需要转化。
//module-1.js代码
function fn(){
console.log(1)
} export default fn
//module-2.js
function fn(){
console.log(2)
} export default fn
//app.js
import x from './module-1.js'
import y from './module-2.js'
x()
y()

最终效果,打开的我的预览链接,使用ctrl+shift+J,会看到打印出1和2


sass-loader

如果使用了预编译的scss语言,要把scss文件变成css并加入到html里面,思路同上,google webpack scss
得到如下代码

npm install sass-loader node-sass webpack --save-dev

模块配置文件

// webpack.config.js
module.exports = {
...
module: {
rules: [{
test: /\.scss$/,
use: [{
loader: "style-loader" // creates style nodes from JS strings
}, {
loader: "css-loader" // translates CSS into CommonJS
}, {
loader: "sass-loader" // compiles Sass to CSS
}]
}]
}
};

这个官方的就比较给力了,很清楚地用法

  • 先用sass-loader把./src/csa/main.scss编译成main.css
  • 再用css-loader把main.css变成符合CommonJS规范的
  • 把main.css变成js字符串,并创建style节点,把它放进去,这样html就可以显示啦。

不过坑爹依旧☺……用的时候报错喽~

第一次就说缺style-loader,好吧……自觉点把另一个一起安装了把。

npm i --save-dev css-loader style-loader


所以,打开我的预览链接,会看到我的预览的背景是灰色的。


此时的webpack.config.js最终代码

const path = require('path');

module.exports = {
entry: './src/js/app.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist/js/')
},
module: {
rules: [
{
test: /\.js$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: 'babel-loader',
options: {
presets: ['env']
}
}
},
{
test: /\.scss$/,
use: [{
loader: "style-loader" // creates style nodes from JS strings
}, {
loader: "css-loader" // translates CSS into CommonJS
}, {
loader: "sass-loader" // compiles Sass to CSS
}]
}
]
}
};

所以借助webpack强大的模块化,通过其构建的依赖关系图(dependency graph)把js、scss都搞到了bundle.js里面,真是牛~

html-loader

本来搞了一个html-loader,优化html,把空格、注释都给压缩掉,提高性能,可是实际使用中也没有报错,也没啥效果,比较尴尬……自己埋个坑后面补一补。

Copy Webpack Plugin

目前呢,前面的loader用的都很爽。在src目录下修改完了代码,一个npx webpack,刷新就可以看到效果了,体验很棒。
但是今天坐在电脑前面,回想代码,以前在前端工程话的道路上,scss、js、html都是被监视着(wacth),开四个命令行窗口,只要src下一有风吹草动,就会把修改后的代码更新过去。

  • 目前使用的webpack可以完全自动化scss、js了,可我如果修改了src/index.html,dist/也无法获知我的修改啊
  • 然后我google一一会,发现了这货Copy Webpack Plugin

哎呀,是个plugin,终于webpack的四大基本概念都到齐了,前面搞了entry output loder,今天用一下plugin

loader 被用于转换某些类型的模块,而插件则可以用于执行范围更广的任务。插件的范围包括,从打包优化和压缩,一直到重新定义环境中的变量。
基本安装

npm i -D copy-webpack-plugin

Copy Webpack Plugin配置文件(plugin的和loader的配置文件可不是一个套路。loader是在module.rules数组的每一个对象里面(即rules数组的每一个value),而plugin是在module的plugins数组里面)

//依然在webpack.config.js
const CopyWebpackPlugin = require('copy-webpack-plugin') const config = {
plugins: [
new CopyWebpackPlugin([ ...patterns ], options)
]
}

Copy Webpack Plugin的github给的代码,一开始把我搞蒙了,和webpack官网的代码不大一样啊。后来才发现原来用了module.exports = config;
在我的小demo里使用的是

plugins: [
new CopyWebpackPlugin([ {
     //原来一个plugin就是一个对象啊,使用的时候实例化对象即可
     from: 'src/index.html', //从src/index.html目录下复制
     to: '../index.html',  //到dist/index.html
     toType: 'file' //复制类型是文件
   }], { copyUnmodified: true }) //把未修改的部分也复制过去
 ]

这个插件可以实现很多功能,具体的细节看这里

关于目录的一个小问题

上面代码为什么这么写呢 to: '../index.html', ,试了好几遍发现没有报错,就是没有结果,最后搞明白了是路径的问题……
还记得 四大基本概念的output里面的path吗,回头看一开始的path

output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist/js/')
},

项目的path是dist/js下,所以应该复制到上一级目录下../也就是dist/目录下了。

可以看到预览链接里面的文字啦

动态效果可以看下图

postcss-loader

上述代码有个小问题使用了display: flexul>li变成了横排,但是这玩意有兼容性。当初我的一篇文章唯一的一个评论就是这么说我的……

检查兼容性(虽然这是严谨要求,我还是老忘),可以去caniuse 看一下,(@ο@) 哇~IE没有绿的哎,支持太差了。( ⊙ o ⊙ )!万一以后我项目搞大了,IE的用户、老安卓的用户想看我项目咋办呢,只能加一下前缀优化一下啦。
有个挺牛的在线的autoprefixer,也可以去在线转换。
既然使用了webpack就Google webpack autoprefixer,遗憾的发现autoprefixer官方推荐使用postcss-loader

postcss-loader解决兼容性问题

先吐槽一下,这货的文档也是稀烂……

  1. 官方安装脚本
npm i -D postcss-loader
  1. 需要单独配置文件postcss.config.js,官方的写法是下面这个(最无语的就是这个……,下面的必错,写出来就是警告大家,官方的也不一定对
module.exports = {
 parser: 'sugarss', // 铪????解析器是sugarss???
 plugins: {
'postcss-import': {},
'postcss-cssnext': {},
'cssnano': {}
}
}

在webpack.config.js的添加时还要注意下面的几点

After setting up your postcss.config.js, add postcss-loader to your webpack.config.js. You can use it standalone or in conjunction with css-loader (recommended). Use it after css-loader and style-loader, but before other preprocessor loaders like e.g sass|less|stylus-loader, if you use any.

这段文档的要点就是让你注意postcss-loader应该在css-loader style-loader之后,但是一定要在其他的预处理器preprocessor loaders之前,例如
sass|less|stylus-loader

  1. 官方给了一个推荐的配置代码
//依然是webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/,
use: [
'style-loader',
{ loader: 'css-loader', options: { importLoaders: 1 } },
'postcss-loader'
]
}
]
}
}

本项目用的是.src/css/main.scss,只能尝试着将上述代码加到相应的位置

rules: [
...
{
test: /\.scss$/,
use: [{
loader: "style-loader" // creates style nodes from JS strings
}, {
loader: "css-loader", options: { importLoaders: 1 }// translates CSS into CommonJS
}, {
loader: "postcss-loader"
}, {
loader: "sass-loader" // compiles Sass to CSS
}]
},
...
  ]

下面的几点可都是官网文档没写的,只能自己踩一踩的坑……


  1. 运行npx webpack,连续报错,不过是缺必备的module的错误,也就是缺postcss.config.js里面的postcss-import postcss-cssnext cssnano sugarss
    没办法,先npm i -D 上面的四个模块名字,依然报错,这次是语法错误

    (⊙v⊙)嗯???它说我不必要的大括号???我这标准的scss语法啊,又不是sass的语法(它省略了大括号和分号),先Google一波这个错误。
    终于在在postcss的issue里面发现了蛛丝马迹,问题果然出在那个令我疑惑的postcss.config.js里面

错误原因分析

  1. 错误的使用了sugarss的解析器(这货和sass类似,没有大括号,所以它说我大括号错了,它的特点是Indent-based CSS syntax for PostCSS.SugarSS MIME-type is text/x-sugarss with .sss file extension.),而我写的是scss语法。
  2. postcss-loader哪来的勇气确定大家都是用的.sss后缀的sugarss语法呢,还敢直接在文档的醒目位置推荐稀烂的postcss.config.js,O__O "…
  3. 那么多的预编译的css语法,果然需要webpack打包工具啊,找到合适的loader去解析啊。

注释掉parser: 'sugarss',这句代码,可以使用默认的解析器去解析了,正常运行了。
不过查看代码,发现好像转换后的css有点小

autoprefixer冗余

仔细观察命令行,发现有线索,一个警告

警告信息提示我说:postcss-cssnext发现有个冗余的autoprefixer插件在我的postcss插件里面,这个可能有不良影响,我应该移除它,因为它已经包括在了postcss-cssnext里面。

webpack的警告说的很明白,postcss-cssnext是无辜的,而且我确定按照官网代码走的,没有安装autoprefixer插件,错误必然在剩下的两个插件里面了。

//修改后的postcss.config.js只剩下这些了
module.exports = {
 plugins: {
   'postcss-import': {}, //1.它错了?
   'postcss-cssnext': {}, //webpack告诉我它是清白的
   'cssnano': {} //2.它错了?
 }
}

我选择了排除法:

  1. 先注释'postcss-import': {},,发现无法转换后的css代码不对,说明它是无辜的。
  2. 那么问题必然是最后一个插件,注释掉'cssnano': {},终于完美了,而且代码很优美。

本着打破砂锅问到底的精神,我搜了一下cssnano,在其官网看到了真实的错误原因,webpack很明智啊,诚不欺我,果然冗余插件了。

cssnano里面有autoprefixer导致了冗余。

extract-text-webpack-plugin

webpack 把所有的资源都当成了一个模块, CSS、JS 文件 都是资源, 都可以打包到一个 bundle.js 文件中.
但是有时候需要把样式 单独的打包成一个文件需要抽离出css文件到单独的css/下。

使用extract-text-webpack-plugin插件可以做到。

  1. 安装脚本
npm install extract-text-webpack-plugin --save-dev
  1. 配置webpack.config.js,官方推荐的配置如下,但是需要结合自己的项目修改一下……
const ExtractTextPlugin = require("extract-text-webpack-plugin"); //插件的套路。都要require进来
module.exports = {
module: {
rules: [
{
test: /\.css$/,
use: ExtractTextPlugin.extract({
fallback: "style-loader", //失败了就用它解析
use: "css-loader" //是css文件,就用这个处理
})
}
]
},
plugins: [
new ExtractTextPlugin("styles.css"),
]
}

目前的问题

我如果使用的是scss,就很尴尬了

最开始由一个错误引起

Google一下,解决掉error,fallbak里面使用了style-loader,use里面不应该使用了,那么问题又来了

  1. 问题一:无法使用style-loader把我的main.scss转化后的css代码插入到style标签里面。

详见代码注释部分

{
test: /\.scss$/,
use: ExtractTextPlugin.extract({
fallback: 'style-loader',
//如果在use里面写上style-loader,就报错window未被定义,可是不写的话,我的bundle.js里面就无法把css放到style标签里面,只能手动把分离的css加到index.html,很无语。
use: [{
loader: "css-loader", options: { importLoaders: 1 }// translates CSS into CommonJS
}, {
loader: "postcss-loader"
}, {
loader: "sass-loader" // compiles Sass to CSS
}]
})
}
  1. 问题2:可以提取出单独的css文件,但是没想到如何放到单独的css/下,很尴尬,代码未提交,还在摸索中。

问题大约知道应该出现在下面这个函数里面

 new ExtractTextPlugin({
filename: (getPath) => {
return getPath('../main.css').replace('../js', '../css'); // 本意是生成在dist/css/main.css,结果只是在dist/main.css目录下,没有css/
},
allChunks: true
})

所有的代码都在我的demo里面。

蛋疼的无力吐槽

算……是……搞定了webpack的基本使用了……吧,最简单的符合我目前技术栈的各种loader,plugin都会安装了。
当然,还有无数的webpack的loader、plugin在前方等着我去探索……各种稀奇古怪的配置文件……痛并快乐着☺

五花八门的配置文件挺让我糟心的……幸亏有了node爸爸帮我啊,webpack爸爸虽然也是比较严厉的,但是省了你用四个命令行窗口的啊,还是很感人的啊。

工具这个东西嘛

  1. 配置出错了怎么办,默念三句

  1. 如果真的搞蹦了怎么办。熊得,送你一句名言

没有什么bug不是一遍webpack解决不了额,如果有的话,那就来三遍webpaack。总有一天让webpack叫你爸爸!!!

新的挑战者parcel

现在的吐槽大概是没有经历过以前更蛋疼的日子吧,幸好有了新的后起之秀---parcel,它的官网老厉害了,智能提示我用了中文,真是贴心。

回顾一下webpack的首页

在对比一下parcel的首页

两者的目的是一样的,不过parcel不需要插件,而且速度快。

快速开始是真的快

快速开始

没有配置,最好以html或者js为入口,直接npm init -y , parcel index.html,可以实现index.js。

它会自动帮你打包到dist目录下的一个js文件里面,并复制index.html过去,而这一切只需要上面的一行代码。

  1. 一开始我的项目的目录结构
  2. 执行parcel index.html的目录结构

而我当时搞webpack的时候的快速开始至少需要安装webpack、webpack.config.js、修改配置内容、安装插件才能实现上述的功能。

模块化和scss的解析很方便

当我在parcel-demo目录下使用parcel index.html的时候,它自动发现我引入了index.js。

<body>
<script src="./index.js"></script>
</body>

  1. 里面的内容是模块化的内容,它自动帮我转成了dist/parcel-demo.js,我在webpack的时候需要babel-loader
  2. 我用的是scss,它也会自动发现,并且竟然

还帮我自动下载了node-sass

其他的特点都在官网去发掘吧~希望日后parcel快速崛起吧


而现在我还是要用webpack的……

爱搞事情的webpack的更多相关文章

  1. sql注入搞事情(连载一)

    SQL注入搞事情(连载一) 概述 写在最前面 为了有个合理的训练计划,山人准备长期开放自己的训练计划以及内容以供大家参考.山人专业是信息对抗技术,不是web方向的博客保证句句手打,如有问题请及时小窗. ...

  2. 搞事情?Spring Boot今天一口气发布三个版本

    学无止境?本文已被 https://www.yourbatman.cn 收录,里面一并有Spring技术栈.MyBatis.JVM.中间件等小而美的专栏供以免费学习.关注公众号[BAT的乌托邦]逐个击 ...

  3. 教你利用Node.js漏洞搞事情

    PentestingNode.js Application : Nodejs Application Security 原文地址:http://www.websecgeeks.com/2017/04/ ...

  4. 搞事情 -- python之线程

    简介 操作系统线程理论 线程概念的引入背景 线程的特点 进程和线程的关系 使用线程的实际场景 用户级线程和内核级线程(了解) 线程和python 理论知识 线程的创建Threading.Thread类 ...

  5. python爬虫24 | 搞事情了,用 Appium 爬取你的微信朋友圈。

    昨天小帅b看到一些事情不顺眼 有人偷换概念 忍不住就写了一篇反讽 996 的 看不下去了,我支持996,年轻人就该996! 没想到有些人看不懂 这就算了 还来骂我 早些时候关注我的小伙伴应该知道我第一 ...

  6. 周六搞事情,微信小程序开发文档已放出!

    程序员们,你们有事干了! 个人感觉不管是什么形式的UI技术,都无法决定一个产品的生死,核心还是服务和模式的创新. 某些方面和ApiCloud好像,但发展前景远远胜过ApiCloud. 微信小程序可以为 ...

  7. bootstrap,bootstrap-table,bootstrapValidator,animate,layer配合起来搞事情

    资源准备(just download) bootstrap: http://www.bootcss.com/ bootstrap-table: http://bootstrap-table.wenzh ...

  8. 【搞事情】VS2015下的openGL初始化

    环境:glfw+glew+visual studio 2015 原材料下载链接: glfw 下载 glew 下载 glm库 下载 cmake 下载 (我下载的时候有些官网戳不开(大概校园网问题)... ...

  9. [daily][CentOS][SELinux]用key免登陆不成功,原来是SElinux在搞事情

    为了提高效率,一般情况下,会把公钥放到sshd主机的 $HOME/.ssh/authorized_keys 文件内. 把私钥放在client的 $HOME/.ssh/ 下. 然后就可以免密登录了.然而 ...

随机推荐

  1. MySQL_数据库命令

    Mysql基础命令 开启MySQL服务:net start mysql 关闭MySQL服务:net stop musql 进入mysql:mysql -h localhost -u root -p 1 ...

  2. win7/xp解除系统限制的网速

    对电脑不熟悉者的方法: 1.单击“开始-开始搜索”,输入“gpedit.msc”,回车后即可打开“组策略对象编辑器”. 2.展开“计算机配置-管理模板-网络-QoS数据包计划程序”,双击右面设置栏中的 ...

  3. spring-boot 使用jdk6(三)

    环境 jdk 6 tomcat 7.0.59 sts 4.4.2 maven 3.2.5 背景 由于环境限制,还在使用 JDK6,所以需要将 spring boot 进行配置,支持JDK6. 以下所有 ...

  4. Linux系列:之软件安装

    1.安装软件 不同的Linux版本可能使用不同的软件管理机制. RPM:使用这类命令进行安装的Linux版本有CentOS. DPKG:使用这类命令进行安装的Linux版本有Debian.Ubuntu ...

  5. hdu 4471 区间条件统计 区间 不超过 x 的元素的个数

    题目传送门//res tp hdu 目的 对长度为n的区间,m次询问,每次提供一个区间两端点与一个值x,求区间内不超过x的元素个数 n 1e5 m 1e5 ai [1,1e9] (i∈[1,n]) 多 ...

  6. 合并两个排序链表——牛客offer

    题目描述: 输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则. 解题思路: 1.一般看到合并这类的题目就会很自然的想到创建一个新的链表,然后将两个链表根据一定 ...

  7. Ioc和Aop底层原理

    Spring中主要用到的设计模式有工厂模式和代理模式. IOC:Inversion of Control控制反转,也叫依赖注入,通过 sessionfactory 去注入实例:IOC就是一个生产和管理 ...

  8. Centos7:ActiveMQ安装,配置及使用

    解压缩ActiveMQ 的压缩包 使用 命令在bin目录下 ./activemq stat//开启 ./activemq stop//关闭 ./activemq status//状态 进入管理后台 U ...

  9. 关于javascript的事件执行机制理解

    理解javascript事件执行机制 众所周知,js是一个单线程的语言,这意味着同一时间只能做一件事,但是我们又说js是异步的.首先,单线程并不是没有优点.作为浏览器脚本语言,JavaScript 的 ...

  10. 1 设置 dev express控件RepositoryItemLookUpEdit数据源的方法

    private void SetLookUpEditData(Type enumType, DevExpress.XtraEditors.Repository.RepositoryItemLookUp ...