webpack打包css缺失3.5分离css没有内容

css3这个相信大家不陌生了,是个非常有趣,神奇的东西!有了css3,js都可以少写很多!我之前也写过关于css3的文章,也封装过css3的一些小动画。个人觉得css3不难,但是很难用得好,用得顺手,最近我也在过一遍css3的一些新特性(不是全部,是我在工作上常用的,或者觉得有用的),以及一些实例,就写了这一篇总结!希望,这篇文章能帮到大家认识css3。写这篇文章主要是让大家能了解css3的一些新特性,以及基础的用法,感觉css3的魅力!如果想要用好css3,这个得靠大家继续努力学习,寻找一些讲得更深入的文章或者书籍了!如果大家有什么其他特性推荐的,欢迎补充!大家一起学习,进步!
看这篇文章,代码可以不用看得过于仔细!这里主要是想让大家了解css3的新特性!代码也是很基础的用法。我给出代码主要是让大家在浏览器运行一下,让大家参考和调试。不要只看代码,只看代码的话,不会知道哪个代码有什么作用的,建议边看效果边看代码。
过渡,是我在项目里面用得最多的一个特性了!也相信是很多人用得最多的一个例子!我平常使用就是想让一些交互效果(主要是hover动画),变得生动一些,不会显得那么生硬!好了,下面进入正文!
引用菜鸟教程的说法:CSS3 过渡是元素从一种样式逐渐改变为另一种的效果。要实现这一点,必须规定两项内容:指定要添加效果的CSS属性指定效果的持续时间。
transition: CSS属性,花费时间,效果曲线(默认ease),延迟时间(默认0)复制代码
/*宽度从原始值到制定值的一个过渡,运动曲线ease,运动时间0.5秒,0.2秒后执行过渡*/
transition:width,.5s,ease,.2s复制代码
/*所有属性从原始值到制定值的一个过渡,运动曲线ease,运动时间0.5秒*/
transition:all,.5s
上面栗子是简写模式,也可以分开写各个属性(这个在下面就不再重复了)
transition-property:
transition-duration: 1s;
transition-timing-function:
transition-delay: 2s;
上面两个按钮,第一个使用了过渡,第二个没有使用过渡,大家可以看到当中的区别,用了过渡之后是不是没有那么生硬,有一个变化的过程,显得比较生动。当然这只是一个最简单的过渡栗子,两个按钮的样式代码,唯一的区别就是,第一个按钮加了过渡代码transition: all .5s;
上面两个菜单,第一个没有使用过渡,第二个使用过渡,大家明显看到区别,使用了过渡看起来也是比较舒服!代码区别就是有过渡的ul的上级元素(祖先元素)有一个类名(ul-transition)。利用这个类名,设置ul的过渡.ul-transition ul{transform-origin: 0 0;transition: all .5s;}
可能大家不知道我在说什么!我贴下代码吧
&div class="demo-hover demo-ul t_c"&
&ul class="fllil"&
&a href="javascript:;"&html&/a&
&li&&a href="#"&div&/a&&/li&
&li&&a href="#"&h1&/a&&/li&
&a href="javascript:;"&js&/a&
&li&&a href="#"&string&/a&&/li&
&li&&a href="#"&array&/a&&/li&
&li&&a href="#"&object&/a&&/li&
&li&&a href="#"&number&/a&&/li&
&a href="javascript:;"&css3&/a&
&li&&a href="#"&transition&/a&&/li&
&li&&a href="#"&animation&/a&&/li&
&a href="javascript:;"&框架&/a&
&li&&a href="#"&vue&/a&&/li&
&li&&a href="#"&react&/a&&/li&
&div class="clear"&&/div&
&div class="demo-hover demo-ul ul-transition t_c"&
&ul class="fllil"&
&a href="javascript:;"&html&/a&
&li&&a href="#"&div&/a&&/li&
&li&&a href="#"&h1&/a&&/li&
&a href="javascript:;"&js&/a&
&li&&a href="#"&string&/a&&/li&
&li&&a href="#"&array&/a&&/li&
&li&&a href="#"&object&/a&&/li&
&li&&a href="#"&number&/a&&/li&
&a href="javascript:;"&css3&/a&
&li&&a href="#"&transition&/a&&/li&
&li&&a href="#"&animation&/a&&/li&
&a href="javascript:;"&框架&/a&
&li&&a href="#"&vue&/a&&/li&
&li&&a href="#"&react&/a&&/li&
&div class="clear"&&/div&
.demo-ul{margin-bottom: 300}
.demo-ul li{
padding: 0 10
width: 100
background:
上面两个可以说是过渡很基础的用法,过渡用法灵活,功能也强大,结合js,可以很轻松实现各种效果(焦点图,手风琴)等,以及很多意想不到的效果。这个靠大家要去挖掘!
动画这个平常用的也很多,主要是做一个预设的动画。和一些页面交互的动画效果,结果和过渡应该一样,让页面不会那么生硬!
animation:动画名称,一个周期花费时间,运动曲线(默认ease),动画延迟(默认0),播放次数(默认1),是否反向播放动画(默认normal),是否暂停动画(默认running)复制代码
/*执行一次logo2-line动画,运动时间2秒,运动曲线为 linear*/
animation: logo2-line 2复制代码
/*2秒后开始执行一次logo2-line动画,运动时间2秒,运动曲线为 linear*/
animation: logo2-line 2s linear 2s;复制代码
/*无限执行logo2-line动画,每次运动时间2秒,运动曲线为 linear,并且执行反向动画*/
animation: logo2-line 2s linea复制代码
还有一个重要属性
animation-fill-mode : none | forwards | backwards |
/*none:不改变默认行为。
forwards :当动画完成后,保持最后一个属性值(在最后一个关键帧中定义)。
backwards:在 animation-delay 所指定的一段时间内,在动画显示之前,应用开始属性值(在第一个关键帧中定义)。
both:向前和向后填充模式都被应用。
这个是我用公司logo写的动画,没那么精细
&!DOCTYPE html&
&html lang="en"&
&meta charset="UTF-8"&
&title&Title&/title&
&link rel="stylesheet" href="reset.css"&
.logo-box{
width: 600
margin: 100
font-size: 0;
.logo-box div{
display: inline-
.logo-box .logo-text{
margin-left: 10
.logo-box .logo1{
animation: logo1 1s ease-in 2s;
animation-fill-mode:
.logo-box .logo-text{
animation: logoText 1s ease-in 3s;
animation-fill-mode:
.logo-box .logo2{
animation: logo2-middle 2s ease-
.logo-box .logo2 img{
animation: logo2-line 2
@keyframes logo1 {
transform:rotate(180deg);
opacity: 0;
transform:rotate(0deg);
opacity: 1;
@keyframes logoText {
transform:translateX(30px);
opacity: 0;
transform:translateX(0);
opacity: 1;
@keyframes logo2-line {
0% { transform: translateX(200px)}
25% { transform: translateX(150px)}
50% { transform: translateX(100px)}
75% { transform: translateX(50px)}
100% { transform: translateX(0); }
@keyframes logo2-middle {
0% { transform: translateY(0);
25% { transform: translateY(-100px);
50% { transform: translateY(0);
75% { transform: translateY(-50px);
100% { transform: translateY(0); }
&div class="logo-box"&
&div class="logo1"&&img src="logo1.jpg"/&&/div&
&div class="logo2"&&img src="logo2.jpg"/&&/div&
&div class="logo-text"&&img src="logo3.jpg"/&&/div&
&div class="wraper"&&div class="item"&&/div&&/div&
下面让大家看一个专业级别的
&!DOCTYPE html&
&html lang="en"&
&meta charset="UTF-8"&
&title&Title&/title&
font-family: Arial,"Helvetica Neue",Helvetica,sans-
background:
这个代码实在太多了,大家直接上网址看吧。
&!DOCTYPE html&
&html lang="en"&
&meta charset="UTF-8"&
&title&纯CSS3模拟跳动的音符效果&/title&
*{margin:0;padding:0;list-style:}
body{background-color:
这一部分,分2d转换和3d转换。有什么好玩的,下面列举几个!
transform:适用于2D或3D转换的元素transform-origin:转换元素的位置(围绕那个点进行转换)。默认(x,y,z):(50%,50%,0)
transform:rotate(30deg);
transform:translate(30px,30px);
transform:scale(.8);
transform: skew(10deg,10deg);
transform:rotateX(180deg);
transform:rotateY(180deg);
transform:rotate3d(10,10,10,90deg);
css3提供的选择器可以让我们的开发,更加方便!这个大家都要了解。下面是css3提供的选择器。
图片来自w3c。这一块建议大家去w3c看(),那里的例子通俗易懂。我不重复讲了。提供的选择器里面,基本都挺好用的。但是我觉得有些不会很常用,比如,:root,:empty,:target,:enabled,:checked。而且几个不推荐使用,网上的说法是性能较差[attribute*=value],[attribute$=value],[attribute^=value],这个我没用过,不太清楚。
以前没有css3的时候,或者需要兼容低版本浏览器的时候,阴影只能用图片实现,但是现在不需要,css3就提供了!
box-shadow: 水平阴影的位置 垂直阴影的位置 模糊距离 阴影的大小 阴影的颜色 阴影开始方向(默认是从里往外,设置inset就是从外往里);
&!DOCTYPE html&
&meta charset="utf-8"&
&title&&/title&
height:100
background:
border-image: 图片url 图像边界向内偏移 图像边界的宽度(默认为边框的宽度) 用于指定在边框外部绘制偏移的量(默认0) 铺满方式--重复(repeat)、拉伸(stretch)或铺满(round)(默认:拉伸(stretch));
边框图片(来自菜鸟教程)
&!DOCTYPE html&
&meta charset="utf-8"&
&title&&/title&
border: 15
padding: 15
border-image: url(border.png);
border-image-slice: 30;
border-image-repeat:
border-image-outset: 0;
&div class="demo"&&/div&
那个更好看,大家看着办
border-radius: n1,n2,n3,n4;
border-radius: n1,n2,n3,n4/n1,n2,n3,n4;
/*n1-n4四个值的顺序是:左上角,右上角,右下角,左下角。*/
&!DOCTYPE html&
&meta charset="utf-8"&
&title&&/title&
border:2px solid
这一块主要讲css3提供背景的三个属性
制定背景绘制(显示)区域
默认情况(从边框开始绘制)
从padding开始绘制(显示),不算border,,相当于把border那里的背景给裁剪掉!(background-clip: padding-)
只在内容区绘制(显示),不算padding和border,相当于把padding和border那里的背景给裁剪掉!(background-clip: content-)
引用菜鸟教程的说法:background-Origin属性指定background-position属性应该是相对位置
下面的div初始的html和css代码都是一样的。如下html
Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat.
&/div&复制代码
padding:35
background:url('logo.png') no-repeat,
下面看下,background-origin不同的三种情况
这个相信很好理解,就是制定背景的大小下面的div初始的html和css代码都是一样的。如下html
Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat.
&/div&复制代码
padding:35
background:url('test.jpg') no-
这个没什么,就是在一张图片,使用多张背景图片,代码如下!html
&p&两张图片的背景&/p&
Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat.
&/div&复制代码
padding:35
background-size:
background:url('test.jpg') no-repeat left,url(logo.png) no-
这个也可以说是倒影,用起来也挺有趣的。
-webkit-box-reflect:方向[ above-上 | below-下 | right-右 | left-左 ],偏移量,遮罩图片复制代码
&p&下倒影&/p&
&p class="reflect-bottom-p"&&img src="test.jpg" class="reflect-bottom"&&/p&复制代码
.reflect-bottom-p {
padding-bottom: 300
.reflect-bottom {
-webkit-box-reflect:
&p&右倒影同时有偏移&/p&
&p&&img src="test.jpg" class="reflect-right-translate"&&/p&复制代码
.reflect-right-translate {
-webkit-box-reflect: right 10
&p&下倒影(渐变)&/p&
&p class="reflect-bottom-p"&&img src="test.jpg" class="reflect-bottom-mask"&&/p&
reflect-bottom-mask {
-webkit-box-reflect: below 0 linear-gradient(transparent, white);
使用的图片
&p&下倒影(png图片)&/p&
&p class="reflect-bottom-p"&&img src="test.jpg" class="reflect-bottom-img"&&/p&
.reflect-bottom-img {
-webkit-box-reflect: below 0 url(shou.png);
语法:word-break: normal|break-all|keep-栗子和运行效果
语法:word-wrap: normal|break-栗子和运行效果
超出省略号这个,主要讲text-overflow这个属性,我直接讲实例的原因是text-overflow的三个写法,clip|ellipsis|string。clip这个方式处理不美观,不优雅。string只在火狐兼容。
这个其实有三行代码,禁止换行,超出隐藏,超出省略号html
&div&This is some long text that will not fit in the box&/div&复制代码
border:1px solid
超出省略号。这个对于大家来说,不难!但是以前如果是多行超出省略号,就只能用js模拟!现在css3提供了多行省略号的方法!遗憾就是这个暂时只支持webkit浏览器!
&!DOCTYPE html&
&meta charset="utf-8"&
&title&&/title&
overflow :
border:1px solid
这样发现边框贴着难看,要撑开一点,但是撑开上下边框不要使用padding!因为会出现下面这个效果。
正确姿势是这样写
overflow :
border:1px solid
这样写,就算在不是webkit内核的浏览器,也可以优雅降级(高度=行高*行数(webkit-line-clamp))!
语法:text-shadow:水平阴影,垂直阴影,模糊的距离,以及阴影的颜色。栗子:text-shadow: 0 0 10px #f00;效果
这个其实就是css3提供了新的颜色表示方法。
一个是rgba(rgb为颜色值,a为透明度)
color: rgba(255,00,00,1);
background: rgba(00,00,00,.5);
h:色相”,“s:饱和度”,“l:亮度”,“a:透明度”这个我姿势了解过,没用过,这里简单给一个例子
color: hsla( 112, 72%, 33%, 0.68);
background-color: hsla( 49, 65%, 60%, 0.68);复制代码
css3的渐变可以说是一大亮点,提供了线性渐变,径向渐变,圆锥渐变(w3c和菜鸟教程都没有提及,是我从一篇文章了解到,但是我自己在谷歌浏览器尝试,却是一个无效的写法!大家如果知道怎么用,请告知!感谢)渐变这一部分,由于用法灵活,功能也强大,这个写起来很长,写一点又感觉没什么意思,我这里贴几个链接教程给大家,在文章我不多说了,毕竟我也是从那几个地方学的,他们写得也是比我好,比我详细!
(这篇就是看我看到圆锥渐变的文章)
css3的滤镜也是一个亮点,功能强大,写法也灵活。
栗子代码如下
&p&原图&/p&
&img src="test.jpg" /&
&p&黑白色filter: grayscale(100%)&/p&
&img src="test.jpg" style="filter: grayscale(100%);"/&
&p&褐色filter:sepia(1)&/p&
&img src="test.jpg" style="filter:sepia(1);"/&
&p&饱和度saturate(2)&/p&
&img src="test.jpg" style="filter:saturate(2);"/&
&p&色相旋转hue-rotate(90deg)&/p&
&img src="test.jpg" style="filter:hue-rotate(90deg);"/&
&p&反色filter:invert(1)&/p&
&img src="test.jpg" style="filter:invert(1);"/&
&p&透明度opacity(.5)&/p&
&img src="test.jpg" style="filter:opacity(.5);"/&
&p&亮度brightness(.5)&/p&
&img src="test.jpg" style="filter:brightness(.5);"/&
&p&对比度contrast(2)&/p&
&img src="test.jpg" style="filter:contrast(2);"/&
&p&模糊blur(3px)&/p&
&img src="test.jpg" style="filter:blur(3px);"/&
&p&阴影drop-shadow(5px 5px 5px
这里说的弹性布局,就是flex;这一块要讲的话,必须要全部讲完,不讲完没什么意思,反而会把大家搞蒙!讲完也是很长,所以,这里我也只贴教程网址。博客讲的很好,很详细!
栅格化布局,就是grid;这一块和flex一样,要讲就必须讲完。这块的内容和flex差不多,也有点长,这里我也贴链接,这个链接讲得也很详细!
这一块,我也是了解过,我觉得多列应该还是挺有用的。虽然我没在项目中用过,下面我简单说下!举个例子!这个属性,建议加私有前缀,兼容性有待提高!html
&div class="newspaper"&
当我年轻的时候,我梦想改变这个世界;当我成熟以后,我发现我不能够改变这个世界,我将目光缩短了些,决定只改变我的国家;当我进入暮年以后,我发现我不能够改变我们的国家,我的最后愿望仅仅是改变一下我的家庭,但是,这也不可能。当我现在躺在床上,行将就木时,我突然意识到:如果一开始我仅仅去改变我自己,然后,我可能改变我的家庭;在家人的帮助和鼓励下,我可能为国家做一些事情;然后,谁知道呢?我甚至可能改变这个世界。
&/div&复制代码
.newspaper
column-count: 3;
-webkit-column-count: 3;
-moz-column-count: 3;
column-rule:2px solid
box-sizing这个属性,网上说法是:属性允许您以特定的方式定义匹配某个区域的特定元素。
这个大家看着可能不知道在说什么,简单粗暴的理解就是:box-sizing:border-box的时候,边框和padding包含在元素的宽高之内!如下图
box-sizing:content-box的时候,边框和padding不包含在元素的宽高之内!如下图
媒体查询,就在监听屏幕尺寸的变化,在不同尺寸的时候显示不同的样式!在做响应式的网站里面,是必不可少的一环!不过由于我最近的项目都是使用rem布局。所以媒体查询就没怎么用了!但是,媒体查询,还是很值得一看的!说不定哪一天就需要用上了!
栗子代码如下
&!DOCTYPE html&
&meta charset="utf-8"&
&title&&/title&
background-color:
@media screen and (max-width: 960px) {
background-color:
@media screen and (max-width: 480px) {
background-color:
&h1&重置浏览器窗口查看效果!&/h1&
&p&如果媒体类型屏幕的可视窗口宽度小于 960 px ,背景颜色将改变。&/p&
&p&如果媒体类型屏幕的可视窗口宽度小于 480 px ,背景颜色将改变。&/p&
混合模式,就像photoshop里面的混合模式!这一块,我了解过,在项目上没用过,但是我觉得这个应该不会没有用武之地!css3的混合模式,两个(background-blend-mode和mix-blend-mode)。这两个写法和显示效果都非常像!区别就在于background-blend-mode是用于同一个元素的背景图片和背景颜色的。mix-blend-mode用于一个元素的背景图片或者颜色和子元素的。看以下代码,区别就出来了!
这一块图片很多,大家看图片快速扫一眼,看下什么效果就好!
&!DOCTYPE html&
&meta charset="UTF-8"&
&title&&/title&
width: 480
height: 300
background:url('test.jpg')no-repeat,
&!DOCTYPE html&
&meta charset="UTF-8"&
&title&&/title&
padding: 20
width: 480
background:
阅读(...) 评论()307.2k 次阅读
日更新,添加了clean-webpack-plugin,babel-env-preset,添加本文涉及到的所有代码的示例,如果你在学习过程中出错了,可
写在前面的话
阅读本文之前,先看下面这个webpack的配置文件,如果每一项你都懂,那本文能带给你的收获也许就比较有限,你可以快速浏览或直接跳过;如果你和十天前的我一样,对很多选项存在着疑惑,那花一段时间慢慢阅读本文,你的疑惑一定一个一个都会消失;如果你以前没怎么接触过Webpack,而你又你对webpack感兴趣,那么动手跟着本文中那个贯穿始终的例子写一次,写完以后你会发现你已明明白白的走进了Webpack的大门。
// 一个常见的`webpack`配置文件
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
module.exports = {
entry: __dirname + "/app/main.js", //已多次提及的唯一入口文件
path: __dirname + "/build",
filename: "bundle-[hash].js"
devtool: 'none',
devServer: {
contentBase: "./public", //本地服务器所加载的页面所在的目录
historyApiFallback: true, //不跳转
inline: true,
test: /(\.jsx|\.js)$/,
loader: "babel-loader"
exclude: /node_modules/
test: /\.css$/,
use: ExtractTextPlugin.extract({
fallback: "style-loader",
loader: "css-loader",
options: {
modules: true,
localIdentName: '[name]__[local]--[hash:base64:5]'
loader: "postcss-loader"
plugins: [
new webpack.BannerPlugin('版权所有,翻版必究'),
new HtmlWebpackPlugin({
template: __dirname + "/app/index.tmpl.html" //new 一个这个插件的实例,并传入相关的参数
new webpack.optimize.OccurrenceOrderPlugin(),
new webpack.optimize.UglifyJsPlugin(),
new ExtractTextPlugin("style.css")
什么是WebPack,为什么要使用它?
为什要使用WebPack
现今的很多网页其实可以看做是功能丰富的应用,它们拥有着复杂的JavaScript代码和一大堆依赖包。为了简化开发的复杂度,前端社区涌现出了很多好的实践方法
模块化,让我们可以把复杂的程序细化为小的文件;
类似于TypeScript这种在JavaScript基础上拓展的开发语言:使我们能够实现目前版本的JavaScript不能直接使用的特性,并且之后还能转换为JavaScript文件使浏览器可以识别;
Scss,less等CSS预处理器
这些改进确实大大的提高了我们的开发效率,但是利用它们开发的文件往往需要进行额外的处理才能让浏览器识别,而手动处理又是非常繁琐的,这就为WebPack类的工具的出现提供了需求。
什么是Webpack
WebPack可以看做是模块打包机:它做的事情是,分析你的项目结构,找到JavaScript模块以及其它的一些浏览器不能直接运行的拓展语言(Scss,TypeScript等),并将其转换和打包为合适的格式供浏览器使用。
WebPack和Grunt以及Gulp相比有什么特性
其实Webpack和另外两个并没有太多的可比性,Gulp/Grunt是一种能够优化前端的开发流程的工具,而WebPack是一种模块化的解决方案,不过Webpack的优点使得Webpack在很多场景下可以替代Gulp/Grunt类的工具。
Grunt和Gulp的工作方式是:在一个配置文件中,指明对某些文件进行类似编译,组合,压缩等任务的具体步骤,工具之后可以自动替你完成这些任务。
Webpack的工作方式是:把你的项目当做一个整体,通过一个给定的主文件(如:index.js),Webpack将从这个文件开始找到你的项目的所有依赖文件,使用loaders处理它们,最后打包为一个(或多个)浏览器可识别的JavaScript文件。
如果实在要把二者进行比较,Webpack的处理速度更快更直接,能打包更多不同类型的文件。
开始使用Webpack
初步了解了Webpack工作方式后,我们一步步的开始学习使用Webpack。
Webpack可以使用npm安装,新建一个空的练习文件夹(此处命名为webpack sample project),在终端中转到该文件夹后执行下述指令就可以完成安装。
//全局安装
npm install -g webpack
//安装到你的项目目录
npm install --save-dev webpack
正式使用Webpack前的准备
在上述练习文件夹中创建一个package.json文件,这是一个标准的npm说明文件,里面蕴含了丰富的信息,包括当前项目的依赖模块,自定义的脚本任务等等。在终端中使用npm init命令可以自动创建这个package.json文件
输入这个命令后,终端会问你一系列诸如项目名称,项目描述,作者等信息,不过不用担心,如果你不准备在npm中发布你的模块,这些问题的答案都不重要,回车默认即可。
package.json文件已经就绪,我们在本项目中安装Webpack作为依赖包
// 安装Webpack
npm install --save-dev webpack
回到之前的空文件夹,并在里面创建两个文件夹,app文件夹和public文件夹,app文件夹用来存放原始数据和我们将写的JavaScript模块,public文件夹用来存放之后供浏览器读取的文件(包括使用webpack打包生成的js文件以及一个index.html文件)。接下来我们再创建三个文件:
index.html --放在public文件夹中;
Greeter.js-- 放在app文件夹中;
main.js-- 放在app文件夹中;
此时项目结构如下图所示
我们在index.html文件中写入最基础的html代码,它在这里目的在于引入打包后的js文件(这里我们先把之后打包后的js文件命名为bundle.js,之后我们还会详细讲述)。
&!-- index.html --&
&!DOCTYPE html&
&html lang="en"&
&meta charset="utf-8"&
&title&Webpack Sample Project&/title&
&div id='root'&
&script src="bundle.js"&&/script&
我们在Greeter.js中定义一个返回包含问候信息的html元素的函数,并依据CommonJS规范导出这个函数为一个模块:
// Greeter.js
module.exports = function() {
var greet = document.createElement('div');
greet.textContent = "Hi there and greetings!";
main.js文件中我们写入下述代码,用以把Greeter模块返回的节点插入页面。
const greeter = require('./Greeter.js');
document.querySelector("#root").appendChild(greeter());
正式使用Webpack
webpack可以在终端中使用,在基本的使用方法如下:
# {extry file}出填写入口文件的路径,本文中就是上述main.js的路径,
# {destination for bundled file}处填写打包文件的存放路径
# 填写路径的时候不用添加{}
webpack {entry file} {destination for bundled file}
指定入口文件后,webpack将自动识别项目所依赖的其它文件,不过需要注意的是如果你的webpack不是全局安装的,那么当你在终端中使用此命令时,需要额外指定其在node_modules中的地址,继续上面的例子,在终端中输入如下命令
# webpack非全局安装的情况
node_modules/.bin/webpack app/main.js public/bundle.js
可以看出webpack同时编译了main.js 和Greeter,js,现在打开index.html,可以看到如下结果
有没有很激动,已经成功的使用Webpack打包了一个文件了。不过在终端中进行复杂的操作,其实是不太方便且容易出错的,接下来看看Webpack的另一种更常见的使用方法。
通过配置文件来使用Webpack
Webpack拥有很多其它的比较高级的功能(比如说本文后面会介绍的loaders和plugins),这些功能其实都可以通过命令行模式实现,但是正如前面提到的,这样不太方便且容易出错的,更好的办法是定义一个配置文件,这个配置文件其实也是一个简单的JavaScript模块,我们可以把所有的与打包相关的信息放在里面。
继续上面的例子来说明如何写这个配置文件,在当前练习文件夹的根目录下新建一个名为webpack.config.js的文件,我们在其中写入如下所示的简单配置代码,目前的配置主要涉及到的内容是入口文件路径和打包后文件的存放路径。
module.exports = {
__dirname + "/app/main.js",//已多次提及的唯一入口文件
path: __dirname + "/public",//打包后的文件存放的地方
filename: "bundle.js"//打包后输出文件的文件名
注:“__dirname”是node.js中的一个全局变量,它指向当前执行脚本所在的目录。
有了这个配置之后,再打包文件,只需在终端里运行webpack(非全局安装需使用node_modules/.bin/webpack)命令就可以了,这条命令会自动引用webpack.config.js文件中的配置选项,示例如下:
又学会了一种使用Webpack的方法,这种方法不用管那烦人的命令行参数,有没有感觉很爽。如果我们可以连webpack(非全局安装需使用node_modules/.bin/webpack)这条命令都可以不用,那种感觉会不会更爽~,继续看下文。
更快捷的执行打包任务
在命令行中输入命令需要代码类似于node_modules/.bin/webpack这样的路径其实是比较烦人的,不过值得庆幸的是npm可以引导任务执行,对npm进行配置后可以在命令行中使用简单的npm start命令来替代上面略微繁琐的命令。在package.json中对scripts对象进行相关设置即可,设置方法如下。
"name": "webpack-sample-project",
"version": "1.0.0",
"description": "Sample webpack project",
"scripts": {
"start": "webpack" // 修改的是这里,JSON文件不支持注释,引用时请清除
"author": "zhang",
"license": "ISC",
"devDependencies": {
"webpack": "3.10.0"
注:package.json中的script会安装一定顺序寻找命令对应位置,本地的node_modules/.bin路径就在这个寻找清单中,所以无论是全局还是局部安装的Webpack,你都不需要写前面那指明详细的路径了。
npm的start命令是一个特殊的脚本名称,其特殊性表现在,在命令行中使用npm start就可以执行其对于的命令,如果对应的此脚本名称不是start,想要在命令行中运行时,需要这样用npm run {script name}如npm run build,我们在命令行中输入npm start试试,输出结果如下:
现在只需要使用npm start就可以打包文件了,有没有觉得webpack也不过如此嘛,不过不要太小瞧webpack,要充分发挥其强大的功能我们需要修改配置文件的其它选项,一项项来看。
Webpack的强大功能
生成Source Maps(使调试更容易)
开发总是离不开调试,方便的调试能极大的提高开发效率,不过有时候通过打包后的文件,你是不容易找到出错了的地方,对应的你写的代码的位置的,Source Maps就是来帮我们解决这个问题的。
通过简单的配置,webpack就可以在打包时为我们生成的source maps,这为我们提供了一种对应编译文件和源文件的方法,使得编译后的代码可读性更高,也更容易调试。
在webpack的配置文件中配置source maps,需要配置devtool,它有以下四种不同的配置选项,各具优缺点,描述如下:
devtool选项
source-map
在一个单独的文件中产生一个完整且功能完全的文件。这个文件具有最好的source map,但是它会减慢打包速度;
cheap-module-source-map
在一个单独的文件中生成一个不带列映射的map,不带列映射提高了打包速度,但是也使得浏览器开发者工具只能对应到具体的行,不能对应到具体的列(符号),会对调试造成不便;
eval-source-map
使用eval打包源文件模块,在同一个文件中生成干净的完整的source map。这个选项可以在不影响构建速度的前提下生成完整的sourcemap,但是对打包后输出的JS文件的执行具有性能和安全的隐患。在开发阶段这是一个非常好的选项,在生产阶段则一定不要启用这个选项;
cheap-module-eval-source-map
这是在打包文件时最快的生成source map的方法,生成的Source Map 会和打包后的JavaScript文件同行显示,没有列映射,和eval-source-map选项具有相似的缺点;
正如上表所述,上述选项由上到下打包速度越来越快,不过同时也具有越来越多的负面作用,较快的打包速度的后果就是对打包后的文件的的执行有一定影响。
对小到中型的项目中,eval-source-map是一个很好的选项,再次强调你只应该开发阶段使用它,我们继续对上文新建的webpack.config.js,进行如下配置:
module.exports = {
devtool: 'eval-source-map',
__dirname + "/app/main.js",
path: __dirname + "/public",
filename: "bundle.js"
cheap-module-eval-source-map方法构建速度更快,但是不利于调试,推荐在大型项目考虑时间成本时使用。
使用webpack构建本地服务器
想不想让你的浏览器监听你的代码的修改,并自动刷新显示修改后的结果,其实Webpack提供一个可选的本地开发服务器,这个本地服务器基于node.js构建,可以实现你想要的这些功能,不过它是一个单独的组件,在webpack中进行配置之前需要单独安装它作为项目依赖
npm install --save-dev webpack-dev-server
devserver作为webpack配置选项中的一项,以下是它的一些配置选项,更多配置可参考
devserver的配置选项
contentBase
默认webpack-dev-server会为根文件夹提供本地服务器,如果想为另外一个目录下的文件提供本地服务器,应该在这里设置其所在目录(本例设置到“public"目录)
设置默认监听端口,如果省略,默认为”8080“
设置为true,当源文件改变时会自动刷新页面
historyApiFallback
在开发单页应用时非常有用,它依赖于HTML5 history API,如果设置为true,所有的跳转将指向index.html
把这些命令加到webpack的配置文件中,现在的配置文件webpack.config.js如下所示
module.exports = {
devtool: 'eval-source-map',
__dirname + "/app/main.js",
path: __dirname + "/public",
filename: "bundle.js"
devServer: {
contentBase: "./public",//本地服务器所加载的页面所在的目录
historyApiFallback: true,//不跳转
inline: true//实时刷新
在package.json中的scripts对象中添加如下命令,用以开启本地服务器:
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "webpack",
"server": "webpack-dev-server --open"
在终端中输入npm run server即可在本地的8080端口查看结果
鼎鼎大名的Loaders登场了!
Loaders是webpack提供的最激动人心的功能之一了。通过使用不同的loader,webpack有能力调用外部的脚本或工具,实现对不同格式的文件的处理,比如说分析转换scss为css,或者把下一代的JS文件(ES6,ES7)转换为现代浏览器兼容的JS文件,对React的开发而言,合适的Loaders可以把React的中用到的JSX文件转换为JS文件。
Loaders需要单独安装并且需要在webpack.config.js中的modules关键字下进行配置,Loaders的配置包括以下几方面:
test:一个用以匹配loaders所处理文件的拓展名的正则表达式(必须)
loader:loader的名称(必须)
include/exclude:手动添加必须处理的文件(文件夹)或屏蔽不需要处理的文件(文件夹)(可选);
query:为loaders提供额外的设置选项(可选)
不过在配置loader之前,我们把Greeter.js里的问候消息放在一个单独的JSON文件里,并通过合适的配置使Greeter.js可以读取该JSON文件的值,各文件修改后的代码如下:
在app文件夹中创建带有问候信息的JSON文件(命名为config.json)
"greetText": "Hi there and greetings from JSON!"
更新后的Greeter.js
var config = require('./config.json');
module.exports = function() {
var greet = document.createElement('div');
greet.textContent = config.greetT
注 由于webpack3.*/webpack2.*已经内置可处理JSON文件,这里我们无需再添加webpack1.*需要的json-loader。在看如何具体使用loader之前我们先看看Babel是什么?
Babel其实是一个编译JavaScript的平台,它可以编译代码帮你达到以下目的:
让你能使用最新的JavaScript代码(ES6,ES7...),而不用管新标准是否被当前使用的浏览器完全支持;
让你能使用基于JavaScript进行了拓展的语言,比如React的JSX;
Babel的安装与配置
Babel其实是几个模块化的包,其核心功能位于称为babel-core的npm包中,webpack可以把其不同的包整合在一起使用,对于每一个你需要的功能或拓展,你都需要安装单独的包(用得最多的是解析Es6的babel-env-preset包和解析JSX的babel-preset-react包)。
我们先来一次性安装这些依赖包
// npm一次性安装多个依赖模块,模块之间用空格隔开
npm install --save-dev babel-core babel-loader babel-preset-env babel-preset-react
在webpack中配置Babel的方法如下:
module.exports = {
entry: __dirname + "/app/main.js",//已多次提及的唯一入口文件
path: __dirname + "/public",//打包后的文件存放的地方
filename: "bundle.js"//打包后输出文件的文件名
devtool: 'eval-source-map',
devServer: {
contentBase: "./public",//本地服务器所加载的页面所在的目录
historyApiFallback: true,//不跳转
inline: true//实时刷新
test: /(\.jsx|\.js)$/,
loader: "babel-loader",
options: {
presets: [
"env", "react"
exclude: /node_modules/
现在你的webpack的配置已经允许你使用ES6以及JSX的语法了。继续用上面的例子进行测试,不过这次我们会使用React,记得先安装 React 和 React-DOM
npm install --save react react-dom
接下来我们使用ES6的语法,更新Greeter.js并返回一个React组件
//Greeter,js
import React, {Component} from 'react'
import config from './config.json';
class Greeter extends Component{
render() {
{config.greetText}
export default Greeter
修改main.js如下,使用ES6的模块定义和渲染Greeter模块
// main.js
import React from 'react';
import {render} from 'react-dom';
import Greeter from './Greeter';
render(&Greeter /&, document.getElementById('root'));
重新使用npm start打包,如果之前打开的本地服务器没有关闭,你应该可以在localhost:8080下看到与之前一样的内容,这说明react和es6被正常打包了。
Babel的配置
Babel其实可以完全在 webpack.config.js 中进行配置,但是考虑到babel具有非常多的配置选项,在单一的webpack.config.js文件中进行配置往往使得这个文件显得太复杂,因此一些开发者支持把babel的配置选项放在一个单独的名为 ".babelrc" 的配置文件中。我们现在的babel的配置并不算复杂,不过之后我们会再加一些东西,因此现在我们就提取出相关部分,分两个配置文件进行配置(webpack会自动调用.babelrc里的babel配置选项),如下:
module.exports = {
entry: __dirname + "/app/main.js",//已多次提及的唯一入口文件
path: __dirname + "/public",//打包后的文件存放的地方
filename: "bundle.js"//打包后输出文件的文件名
devtool: 'eval-source-map',
devServer: {
contentBase: "./public",//本地服务器所加载的页面所在的目录
historyApiFallback: true,//不跳转
inline: true//实时刷新
test: /(\.jsx|\.js)$/,
loader: "babel-loader"
exclude: /node_modules/
//.babelrc
"presets": ["react", "env"]
到目前为止,我们已经知道了,对于模块,Webpack能提供非常强大的处理功能,那那些是模块呢。
一切皆模块
Webpack有一个不可不说的优点,它把所有的文件都都当做模块处理,JavaScript代码,CSS和fonts以及图片等等通过合适的loader都可以被处理。
webpack提供两个工具处理样式表,css-loader 和 style-loader,二者处理的任务不同,css-loader使你能够使用类似@import 和 url(...)的方法实现 require()的功能,style-loader将所有的计算后的样式加入页面中,二者组合在一起使你能够把样式表嵌入webpack打包后的JS文件中。
继续上面的例子
npm install --save-dev style-loader css-loader
module.exports = {
test: /(\.jsx|\.js)$/,
loader: "babel-loader"
exclude: /node_modules/
test: /\.css$/,
loader: "style-loader"
loader: "css-loader"
请注意这里对同一个文件引入多个loader的方法。
接下来,在app文件夹里创建一个名字为"main.css"的文件,对一些元素设置样式
/* main.css */
box-sizing: border-
-ms-text-size-adjust: 100%;
-webkit-text-size-adjust: 100%;
*, *:before, *:after {
box-sizing:
margin: 0;
font-family: 'Helvetica Neue', Helvetica, Arial, sans-
h1, h2, h3, h4, h5, h6, p, ul {
margin: 0;
padding: 0;
我们这里例子中用到的webpack只有单一的入口,其它的模块需要通过 import, require, url等与入口文件建立其关联,为了让webpack能找到”main.css“文件,我们把它导入”main.js “中,如下
import React from 'react';
import {render} from 'react-dom';
import Greeter from './Greeter';
import './main.css';//使用require导入css文件
render(&Greeter /&, document.getElementById('root'));
通常情况下,css会和js打包到同一个文件中,并不会打包为一个单独的css文件,不过通过合适的配置webpack也可以把css打包为单独的文件的。
上面的代码说明webpack是怎么把css当做模块看待的,咱们继续看一个更加真实的css模块实践。
CSS module
在过去的一些年里,JavaScript通过一些新的语言特性,更好的工具以及更好的实践方法(比如说模块化)发展得非常迅速。模块使得开发者把复杂的代码转化为小的,干净的,依赖声明明确的单元,配合优化工具,依赖管理和加载管理可以自动完成。
不过前端的另外一部分,CSS发展就相对慢一些,大多的样式表却依旧巨大且充满了全局类名,维护和修改都非常困难。
被称为CSS modules的技术意在把JS的模块化思想带入CSS中来,通过CSS模块,所有的类名,动画名默认都只作用于当前模块。Webpack对CSS模块化提供了非常好的支持,只需要在CSS loader中进行简单配置即可,然后就可以直接把CSS的类名传递到组件的代码中,这样做有效避免了全局污染。具体的代码如下
module.exports = {
test: /(\.jsx|\.js)$/,
loader: "babel-loader"
exclude: /node_modules/
test: /\.css$/,
loader: "style-loader"
loader: "css-loader",
options: {
modules: true, // 指定启用css modules
localIdentName: '[name]__[local]--[hash:base64:5]' // 指定css的类名格式
我们在app文件夹下创建一个Greeter.css文件来进行一下测试
/* Greeter.css */
background-color: #
padding: 10
border: 3px solid #
导入.root到Greeter.js中
import React, {Component} from 'react';
import config from './config.json';
import styles from './Greeter.css';//导入
class Greeter extends Component{
render() {
&div className={styles.root}& //使用cssModule添加类名的方法
{config.greetText}
export default Greeter
放心使用把,相同的类名也不会造成不同组件之间的污染。
CSS modules 也是一个很大的主题,有兴趣的话可以去其了解更多。
CSS预处理器
Sass 和 Less 之类的预处理器是对原生CSS的拓展,它们允许你使用类似于variables, nesting, mixins, inheritance等不存在于CSS中的特性来写CSS,CSS预处理器可以这些特殊类型的语句转化为浏览器可识别的CSS语句,
你现在可能都已经熟悉了,在webpack里使用相关loaders进行配置就可以使用了,以下是常用的CSS 处理loaders:
Less Loader
Sass Loader
Stylus Loader
不过其实也存在一个CSS的处理平台-PostCSS,它可以帮助你的CSS实现更多的功能,在其可了解更多相关知识。
举例来说如何使用PostCSS,我们使用PostCSS来为CSS代码自动添加适应不同浏览器的CSS前缀。
首先安装postcss-loader 和 autoprefixer(自动添加前缀的插件)
npm install --save-dev postcss-loader autoprefixer
接下来,在webpack配置文件中添加postcss-loader,在根目录新建postcss.config.js,并添加如下代码之后,重新使用npm start打包时,你写的css会自动根据Can i use里的数据添加不同前缀了。
//webpack.config.js
module.exports = {
test: /(\.jsx|\.js)$/,
loader: "babel-loader"
exclude: /node_modules/
test: /\.css$/,
loader: "style-loader"
loader: "css-loader",
options: {
modules: true
loader: "postcss-loader"
// postcss.config.js
module.exports = {
plugins: [
require('autoprefixer')
至此,本文已经谈论了处理JS的Babel和处理CSS的PostCSS的基本用法,它们其实也是两个单独的平台,配合webpack可以很好的发挥它们的作用。接下来介绍Webpack中另一个非常重要的功能-Plugins
插件(Plugins)
插件(Plugins)是用来拓展Webpack功能的,它们会在整个构建过程中生效,执行相关的任务。Loaders和Plugins常常被弄混,但是他们其实是完全不同的东西,可以这么来说,loaders是在打包构建过程中用来处理源文件的(JSX,Scss,Less..),一次处理一个,插件并不直接操作单个文件,它直接对整个构建过程其作用。
Webpack有很多内置插件,同时也有很多第三方插件,可以让我们完成更加丰富的功能。
使用插件的方法
要使用某个插件,我们需要通过npm安装它,然后要做的就是在webpack配置中的plugins关键字部分添加该插件的一个实例(plugins是一个数组)继续上面的例子,我们添加了一个给打包后代码。
const webpack = require('webpack');
module.exports = {
test: /(\.jsx|\.js)$/,
loader: "babel-loader"
exclude: /node_modules/
test: /\.css$/,
loader: "style-loader"
loader: "css-loader",
options: {
modules: true
loader: "postcss-loader"
plugins: [
new webpack.BannerPlugin('版权所有,翻版必究')
通过这个插件,打包后的JS文件显示如下
这就是webpack插件的基础用法了,下面给大家推荐几个常用的插件
HtmlWebpackPlugin
这个插件的作用是依据一个简单的index.html模板,生成一个自动引用你打包后的JS文件的新index.html。这在每次生成的js文件名称不同时非常有用(比如添加了hash值)。
npm install --save-dev html-webpack-plugin
这个插件自动完成了我们之前手动做的一些事情,在正式使用之前需要对一直以来的项目结构做一些更改:
移除public文件夹,利用此插件,index.html文件会自动生成,此外CSS已经通过前面的操作打包到JS中了。
在app目录下,创建一个index.tmpl.html文件模板,这个模板包含title等必须元素,在编译过程中,插件会依据此模板生成最终的html页面,会自动添加所依赖的 css, js,favicon等文件,index.tmpl.html中的模板源代码如下:
&!DOCTYPE html&
&html lang="en"&
&meta charset="utf-8"&
&title&Webpack Sample Project&/title&
&div id='root'&
3.更新webpack的配置文件,方法同上,新建一个build文件夹用来存放最终的输出文件
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: __dirname + "/app/main.js",//已多次提及的唯一入口文件
path: __dirname + "/build",
filename: "bundle.js"
devtool: 'eval-source-map',
devServer: {
contentBase: "./public",//本地服务器所加载的页面所在的目录
historyApiFallback: true,//不跳转
inline: true//实时刷新
test: /(\.jsx|\.js)$/,
loader: "babel-loader"
exclude: /node_modules/
test: /\.css$/,
loader: "style-loader"
loader: "css-loader",
options: {
modules: true
loader: "postcss-loader"
plugins: [
new webpack.BannerPlugin('版权所有,翻版必究'),
new HtmlWebpackPlugin({
template: __dirname + "/app/index.tmpl.html"//new 一个这个插件的实例,并传入相关的参数
再次执行npm start你会发现,build文件夹下面生成了bundle.js和index.html。
Hot Module Replacement
Hot Module Replacement(HMR)也是webpack里很有用的一个插件,它允许你在修改组件代码后,自动刷新实时预览修改后的效果。
在webpack中实现HMR也很简单,只需要做两项配置
在webpack配置文件中添加HMR插件;
在Webpack Dev Server中添加“hot”参数;
不过配置完这些后,JS模块其实还是不能自动热加载的,还需要在你的JS模块中执行一个Webpack提供的API才能实现热加载,虽然这个API不难使用,但是如果是React模块,使用我们已经熟悉的Babel可以更方便的实现功能热加载。
整理下我们的思路,具体实现方法如下
Babel和webpack是独立的工具
二者可以一起工作
二者都可以通过插件拓展功能
HMR是一个webpack插件,它让你能浏览器中实时观察模块修改后的效果,但是如果你想让它工作,需要对模块进行额外的配额;
Babel有一个叫做react-transform-hrm的插件,可以在不对React模块进行额外的配置的前提下让HMR正常工作;
还是继续上例来实际看看如何配置
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: __dirname + "/app/main.js",//已多次提及的唯一入口文件
path: __dirname + "/build",
filename: "bundle.js"
devtool: 'eval-source-map',
devServer: {
contentBase: "./public",//本地服务器所加载的页面所在的目录
historyApiFallback: true,//不跳转
inline: true,
test: /(\.jsx|\.js)$/,
loader: "babel-loader"
exclude: /node_modules/
test: /\.css$/,
loader: "style-loader"
loader: "css-loader",
options: {
modules: true
loader: "postcss-loader"
plugins: [
new webpack.BannerPlugin('版权所有,翻版必究'),
new HtmlWebpackPlugin({
template: __dirname + "/app/index.tmpl.html"//new 一个这个插件的实例,并传入相关的参数
new webpack.HotModuleReplacementPlugin()//热加载插件
安装react-transform-hmr
npm install --save-dev babel-plugin-react-transform react-transform-hmr
// .babelrc
"presets": ["react", "env"],
"development": {
"plugins": [["react-transform", {
"transforms": [{
"transform": "react-transform-hmr",
"imports": ["react"],
"locals": ["module"]
现在当你使用React时,可以热加载模块了,每次保存就能在浏览器上看到更新内容。
产品阶段的构建
目前为止,我们已经使用webpack构建了一个完整的开发环境。但是在产品阶段,可能还需要对打包的文件进行额外的处理,比如说优化,压缩,缓存以及分离CSS和JS。
对于复杂的项目来说,需要复杂的配置,这时候分解配置文件为多个小的文件可以使得事情井井有条,以上面的例子来说,我们创建一个webpack.production.config.js的文件,在里面加上基本的配置,它和原始的webpack.config.js很像,如下
// webpack.production.config.js
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: __dirname + "/app/main.js", //已多次提及的唯一入口文件
path: __dirname + "/build",
filename: "bundle.js"
devtool: 'null', //注意修改了这里,这能大大压缩我们的打包代码
devServer: {
contentBase: "./public", //本地服务器所加载的页面所在的目录
historyApiFallback: true, //不跳转
inline: true,
test: /(\.jsx|\.js)$/,
loader: "babel-loader"
exclude: /node_modules/
test: /\.css$/,
use: ExtractTextPlugin.extract({
fallback: "style-loader",
loader: "css-loader",
options: {
modules: true
loader: "postcss-loader"
plugins: [
new webpack.BannerPlugin('版权所有,翻版必究'),
new HtmlWebpackPlugin({
template: __dirname + "/app/index.tmpl.html" //new 一个这个插件的实例,并传入相关的参数
new webpack.HotModuleReplacementPlugin() //热加载插件
//package.json
"name": "test",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "webpack",
"server": "webpack-dev-server --open",
"build": "NODE_ENV=production webpack --config ./webpack.production.config.js --progress"
"author": "",
"license": "ISC",
"devDependencies": {
"dependencies": {
"react": "^15.6.1",
"react-dom": "^15.6.1"
注意:如果是window电脑,build需要配置为"build": "set NODE_ENV=production && webpack --config ./webpack.production.config.js --progress".谢谢评论区简友提醒。
webpack提供了一些在发布阶段非常有用的优化插件,它们大多来自于webpack社区,可以通过npm安装,通过以下插件可以完成产品发布阶段所需的功能
OccurenceOrderPlugin :为组件分配ID,通过这个插件webpack可以分析和优先考虑使用最多的模块,并为它们分配最小的ID
UglifyJsPlugin:压缩JS代码;
ExtractTextPlugin:分离CSS和JS文件
我们继续用例子来看看如何添加它们,OccurenceOrder 和 UglifyJS plugins 都是内置插件,你需要做的只是安装其它非内置插件
npm install --save-dev extract-text-webpack-plugin
在配置文件的plugins后引用它们
// webpack.production.config.js
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
module.exports = {
entry: __dirname + "/app/main.js",//已多次提及的唯一入口文件
path: __dirname + "/build",
filename: "bundle.js"
devtool: 'none',
devServer: {
contentBase: "./public",//本地服务器所加载的页面所在的目录
historyApiFallback: true,//不跳转
inline: true,
test: /(\.jsx|\.js)$/,
loader: "babel-loader"
exclude: /node_modules/
test: /\.css$/,
loader: "style-loader"
loader: "css-loader",
options: {
modules: true
loader: "postcss-loader"
plugins: [
new webpack.BannerPlugin('版权所有,翻版必究'),
new HtmlWebpackPlugin({
template: __dirname + "/app/index.tmpl.html"
new webpack.optimize.OccurrenceOrderPlugin(),
new webpack.optimize.UglifyJsPlugin(),
new ExtractTextPlugin("style.css")
此时执行npm run build可以看见代码是被压缩后的
缓存无处不在,使用缓存的最好方法是保证你的文件名和文件内容是匹配的(内容改变,名称相应改变)
webpack可以把一个哈希值添加到打包的文件名中,使用方法如下,添加特殊的字符串混合体([name], [id] and [hash])到输出文件名前
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
module.exports = {
path: __dirname + "/build",
filename: "bundle-[hash].js"
现在用户会有合理的缓存了。
去除build文件中的残余文件
添加了hash之后,会导致改变文件内容后重新打包时,文件名不同而内容越来越多,因此这里介绍另外一个很好用的插件clean-webpack-plugin。
安装:cnpm install clean-webpack-plugin --save-dev
引入clean-webpack-plugin插件后在配置文件的plugins中做相应配置即可:
const CleanWebpackPlugin = require("clean-webpack-plugin");
plugins: [
...// 这里是之前配置的其它各种插件
new CleanWebpackPlugin('build/*.*', {
root: __dirname,
verbose: true,
dry: false
关于clean-webpack-plugin的详细使用可参考
其实这是一年前的文章了,趁周末重新运行和修改了一下,现在所有的代码都可以正常运行,所用webpack基于最新的webpack3.5.3。希望依旧能对你有帮助。
这是一篇好长的文章,谢谢你的耐心,能仔细看到了这里,大概半个月前我第一次自己一步步配置项目所需的Webpack后就一直想写一篇笔记做总结,几次动笔都不能让自己满意,总觉得写不清楚。其实关于Webpack本文讲述得仍不完全,不过相信你看完后已经进入Webpack的大门,能够更好的探索其它的关于Webpack的知识了。
欢迎大家在文后发表自己的观点讨论。
更新,修改css module部分代码及示例图片,css module真的非常好用,希望大家都能用上。
日更新,添加了一个使用webpack配置多页应用的demo,可以点击
日更新,本文依据webpack3.5.3将文章涉及代码完全重写,所有代码都在Mac上正常运行过。希望依旧对你学习webpack有帮助。
号更新:最近在Gitchat上将发起了一场关于webpack的分享,目的在于一起花最短的时间理解和学会webpack,感兴趣的童鞋可以微信扫描注册哈。
607 收藏&&|&&1749
浪费这么长时间,我靠
浪费这么长时间,我靠
浪费多少时间你心里没点*数吗?(滑稽脸)
浪费多少时间你心里没点*数吗?(滑稽脸)
你能说出这种话我理解你,也许你是某个BAT的大神,但是作为前端菜鸟,这篇文章到刚刚为止我已经看过7遍,并且每次都有新的领悟,在这个过程中,面试能力也不断提高,实习的公司也在提升,从一开始的TalkingData到汽车之家,再到拿到百度外卖的校招offer和京东的offer。
你能说出这种话我理解你,也许你是某个BAT的大神,但是作为前端菜鸟,这篇文章到刚刚为止我已经看过7遍,并且每次都有新的领悟,在这个过程中,面试能力也不断提高,实习的公司也在提升,从一开始的TalkingData到汽车之家,再到拿到百度外卖的校招offer和京东的offer。
兄弟赞一个
@Leeyj[leeyj] 兄弟赞一个
Greeter.js只包括一个用来返回包含问候信息的html元素的函数。下面的和main.js 代码写反了。
2.错误 module: {//在配置文件里添加JSON loader
loaders: [
test: /\.json$/,
loader: "json"//应该是json-loader
Greeter.js只包括一个用来返回包含问候信息的html元素的函数。下面的和main.js 代码写反了。
module: {//在配置文件里添加JSON loader
loaders: [
test: /\.json$/,
loader: &json&//应该是json-loader
webpack2.x以后json-loader is not required anymore
webpack2.x以后json-loader is not required anymore
我想说这比一些教程要好的很多,初学者可能会迷茫在各个配置的作用和说明,但这个解释的就算可以了,希望可以出个进阶篇!
我想说这比一些教程要好的很多,初学者可能会迷茫在各个配置的作用和说明,但这个解释的就算可以了,希望可以出个进阶篇!
求教:按照本教程只能打包出一个js文件,业务代码和第三方库(如React.js)都在这个代码中。如果业务代码一旦有改动,整个js代码的缓存都失效。讲自己写的代码(易改动)和第三方库代码(不易改动)分别打包成 app.js 和 third.js ?这样更利于缓存
求教:按照本教程只能打包出一个js文件,业务代码和第三方库(如React.js)都在这个代码中。如果业务代码一旦有改动,整个js代码的缓存都失效。讲自己写的代码(易改动)和第三方库代码(不易改动)分别打包成 app.js 和 third.js ?这样更利于缓存
window下运行,修改如下:NODE_ENV=production
是linux设置变量的方法,windows需要用set
set NODE_ENV=production && webpack -p --config --progress
window下运行,修改如下:
NODE_ENV=production
是linux设置变量的方法,
windows需要用set
set NODE_ENV=production && webpack -p --config --progress
我完整的是 "build": "set NODE_ENV=production && webpack -p --config ./webpack.production.config.js --progress" 这样才build 成功的
我完整的是 &build&: &set NODE_ENV=production && webpack -p --config ./webpack.production.config.js --progress& 这样才build 成功的
请问打包后的文件怎么看啊?
请问打包后的文件怎么看啊?
兼容环境变量可以使用 cross-env 包。
兼容环境变量可以使用 cross-env 包。
挺好的, 入门了.就是现在已经webpack 3.0了, 这篇文章是基于1.x的. 1.x和2.x有很多地方不兼容, 这个花了点时间.另外webpack-dev-server这块写的不够清楚, 绕了点路.总体确实把一些常用的功能覆盖了.附上一份能跑通的demo
挺好的, 入门了.
就是现在已经webpack 3.0了, 这篇文章是基于1.x的. 1.x和2.x有很多地方不兼容, 这个花了点时间.
另外webpack-dev-server这块写的不够清楚, 绕了点路.
总体确实把一些常用的功能覆盖了.
附上一份能跑通的demo
https://github.com/helloint/helloint.github.io/tree/master/demo/webpack-test
这demo真是极好的!!
这demo真是极好的!!
看到这篇文章时webpack已经是4.6.0了,看完一步步走下来,基本都是可以运行的,除了最后面优化插件这节时,有两个小问题是:1.UglifyJsPlugin插件已经不需要了,只需要以下配置即可,并且production mode下面自动为trueoptimization: {
minimize: true
}2.ExtractTextPlugin不能用了,会报以下错误,网上说可以换另一个css的插件,或者有一个其它的办法,没看懂Error: Chunk.entrypoints: Use Chunks.groupsIterable and filter by instanceof Entrypoint instead最后感谢博主,这篇文章确实配得上这个标题!
看到这篇文章时webpack已经是4.6.0了,看完一步步走下来,基本都是可以运行的,除了最后面优化插件这节时,有两个小问题是:
1.UglifyJsPlugin插件已经不需要了,只需要以下配置即可,并且production mode下面自动为true
optimization: {
minimize: true
2.ExtractTextPlugin不能用了,会报以下错误,网上说可以换另一个css的插件,或者有一个其它的办法,没看懂
Error: Chunk.entrypoints: Use Chunks.groupsIterable and filter by instanceof Entrypoint instead
最后感谢博主,这篇文章确实配得上这个标题!
第二个问题可以重新安装 npm install --save-dev extract-text-webpack-plugin@next
第二个问题可以重新安装 npm install --save-dev extract-text-webpack-plugin@next
2018了,webpack已经4.x,楼主这篇有点不适用了。首先就是webpack app/main.js public/bundle.js 这句话执行后,就提醒你安装webpack-cli或者webpack-command,结果安多少次都没用。后来直接用npx webpack app/main.js --output public/bundle.js ,才成功
2018了,webpack已经4.x,楼主这篇有点不适用了。首先就是webpack app/main.js public/bundle.js 这句话执行后,就提醒你安装webpack-cli或者webpack-command,结果安多少次都没用。后来直接用npx webpack app/main.js --output public/bundle.js ,才成功
确实看这篇就能入门了,感谢博主!
确实看这篇就能入门了,感谢博主!
{extry file}出填写入口文件的路径,本文中就是上述main.js的路径,
{destination for bundled file}处填写打包文件的存放路径
填写路径的时候不用添加{}
webpack {entry file} {destination for bundled file}我走到这步就卡住了,报错{ Error: Cannot find module 'webpack-cli'
at Function.Module._resolveFilename (module.js:555:15)
at Function.Module._load (module.js:482:25)
at Module.require (module.js:604:17)
at require (internal/module.js:11:18)
at runCommand.then.result (/usr/local/Cellar/nvm/0.33.8/versions/node/v9.4.0/lib/node_modules/webpack/bin/webpack.js:62:14)
at &anonymous&
at process._tickCallback (internal/process/next_tick.js:160:7) code: 'MODULE_NOT_FOUND' }
# {extry file}出填写入口文件的路径,本文中就是上述main.js的路径,
# {destination for bundled file}处填写打包文件的存放路径
# 填写路径的时候不用添加{}
webpack {entry file} {destination for bundled file}
我走到这步就卡住了,报错
{ Error: Cannot find module 'webpack-cli'
at Function.Module._resolveFilename (module.js:555:15)
at Function.Module._load (module.js:482:25)
at Module.require (module.js:604:17)
at require (internal/module.js:11:18)
at runCommand.then.result (/usr/local/Cellar/nvm/0.33.8/versions/node/v9.4.0/lib/node_modules/webpack/bin/webpack.js:62:14)
at &anonymous&
at process._tickCallback (internal/process/next_tick.js:160:7) code: 'MODULE_NOT_FOUND' }
找到这里说可以实现,不过我还没验证
找到这里说可以实现,不过我还没验证 https://segmentfault.com/a/2052#articleHeader9
非常非常感谢!有没有进阶版的?很期待新的分享!
非常非常感谢!有没有进阶版的?很期待新的分享!
devServer:{
colors: true,会报错,应该为
stats: { colors: true },
devServer:{
colors: true,会报错,应该为
stats: { colors: true },
非常强大,谢谢博主
非常强大,谢谢博主
专门注册个账号来赞这篇文章
专门注册个账号来赞这篇文章
精华好文章,都是干货!已打赏5元并订阅GItChat!
精华好文章,都是干货!已打赏5元并订阅GItChat!
为什么是windows报错呢
为什么是windows报错呢
使用的Windows系统导致的错误?
使用的Windows系统导致的错误?
不错~感谢作者和博主的翻译
不错~感谢作者和博主的翻译
十分感谢,终于感觉清楚了很多
十分感谢,终于感觉清楚了很多
很好的入门文章,感谢!
很好的入门文章,感谢!
分享到微博?
我要该,理由是:
在 SegmentFault,学习技能、解决问题
每个月,我们帮助 1000 万的开发者解决各种各样的技术问题。并助力他们在技术能力、职业生涯、影响力上获得提升。

我要回帖

更多关于 webpackcss抽取 的文章

 

随机推荐