2017/12/18/更新
已经有一段时间没有更新webpack了,从如今的角度看,文章有一部份内容也是不够成熟,后续仍是会继续梳理更新的。css
网上关于webpack的教程已经数不胜数了,也无心再从新写一篇复制文。可是实际操做过程当中,发现各类教程版本都不一致,有的教程已通过时了,有的教程模糊不清,所以仍是遇到了各类问题,所以特将自身实际操做过程当中遇到的问题记录下来,并附上相应的示例demo,也但愿能给他人带来帮助!html
本文主要是记录的一些遇到的问题以及提供了示例,若是想要看入门教程仍是去官网上或者参考参考资源中的连接。node
问题记录较多,想要直接看示例Demo的请拉到最下方。webpack
另外,此文会持续更新。git
README
说明:项目的package.json中,只要带有注释,必然编译不能经过github
解决:禁止在package.json中注释web
说明:在最开始作项目时,因为本地已经全局安装过了对应的依赖包,所以没有再从新在本地安装,致使运行时报错,全局安装版本与本地依赖的版本不一致致使。算法
解决:每个项目中,全部的依赖包均在本地安装,依赖状况经过npm install *** --save -dev
注入package.json
中,其中一些环境之外的依赖,好比第三方库express
等能够经过npm install *** --save
安装。express
全部的依赖包都在本地安装是一个好习惯,由于这样能够随时打包带走与从新装箱。npm
css-loader
省略-loader
带来的问题说明:在老版本的webpack中,常常会用省略的写法来写loader,好比
loaders: [{ test: /\.css$/, loader: "style!css" }],
可是,使用此种写法后,编译时会报错。
解决:如今新版本中,已经不容许省略了,好比使用全称,好比:
loaders: [{ test: /\.css$/, loader: "style-loader!css-loader" }],
require(css)
后,样式嵌入在js中,没有独立的css文件说明:webpack的默认设置中,若是没有引入特殊的第三方插件,在js中require的css文件是会自动写入到相应打包出的js中的,这样一来有一些缺点:
解决:须要引入一个第三方插件extract-text-webpack-plugin
,具体以下:
//头部引入css打包插件 const ExtractTextPlugin = require("extract-text-webpack-plugin"); //声明对应的loaders loaders: [{ test: /\.css$/, //请注意loader里的写法,有一些低版本的例子中是过期的写法 loader: ExtractTextPlugin.extract({ fallback: "style-loader", use: "css-loader" }) }], plugins: [ ... //这样会定义,全部js文件中经过require引入的css都会被打包成相应文件名字的css new ExtractTextPlugin("[name].css"), ],
注意,以上loaders和plugins中都必须声明,缺一不可
说明:最初在引用ExtractTextPlugin 插件时,使用了以下写法,致使了报错
loaders: [{ test: /\.css$/, loader: ExtractTextPlugin.extract(["style-loader","css-loader"]) }],
解决:缘由是这种写法已通过时,根据命令台中的提示,修改成最新写法便可:
loaders: [{ test: /\.css$/, loader: ExtractTextPlugin.extract({ fallback: "style-loader", use: "css-loader" }) }],
require(html)
不会输出成html说明:在使用webpack时,习惯性的用了万物皆模块这个概念,因而在js中引入html,以下:
//***.js中 require('./index.html') ...
结果是并不会生成一个index.html的文件,而是会将html代码嵌入到js中,做为模块代码而存在。
解决: 通常webpack项目中,会用htmlPagePluginConfig
插件来引入html(这时候会给每个html制定一个入口js文件),而后接下来全部操做均可以从这个入口js文件中进行(好比引入css,好比逻辑操做)
须要注意的是,这个插件声明html时,对应引入的js路径必定要对,如:
{ template: 'pages/index.html', // 若是是只声明index,因为路径不对,则不会自动插入 chunks: ['js/index'], }
说明:开发过程当中使用的htmlPagePluginConfig
插件加载html,可是发现构建过程当中,html内部引入的img等标签不会被自动替换。
解决:须要引入html-loader
插件,有了这个插件后,引入,默认会将html内部的img自动替换掉
link(css)
后,不会替换对应的css,或者是会报错说明:正常开发是全部css都是在js中引入的,可是在某一次尝试中,准备尝试在html里用原始的link方式引入css,并引入了html-loader,以下:
<meta charset="utf-8" /> <link rel="stylesheet" href="test.css" />
loaders: [{ test: /\.html$/, use: [{ loader: 'html-loader', options: { minimize: false, } }],
结果按上述的方法进行后发现对于的html里的css路径没有替换,这时发现html-loader
默认是不会替换css,因而又作以下改动
loaders: [{ test: /\.html$/, use: [{ loader: 'html-loader', options: { minimize: false, //开启link的替换 attrs: ['img:src', 'link:href'] } }],
可是采用上述配置后,提示:Error: "extract-text-webpack-plugin" loader is used without the corresponding plugin
解决:webpack中ExtractTextPlugin须要配合js模块化引入css使用。
若是想要实现html内部linkcss,目前没有找到完美的解决方法,只知道使用webpack构建项目时,css都经过js require
引入就不会有错了
.min.css
重复压缩会报错说明:在项目中引入第三方lib文件后,发现,若是引入的文件自己已经压缩过了(如min.css文件),这时候再采用压缩配置css-loader?minimize
,则会报错
解决:采用了正在表达式进行了过滤,含有.min.css的文件不会压缩,其它css则会压缩,以下:
loaders: [{ //20170314更新:如下是错误写法,好比common.css也没法匹配的 //test: /[^((?!\.min\.css).)*$]\.css$/, //如下是正确写法 test: /^((?!\.min\.css).)*\.css/, loader: ExtractTextPlugin.extract({ fallback: "style-loader", use: "css-loader?minimize&-autoprefixer" }) }, { test: /\.min\.css$/, loader: ExtractTextPlugin.extract({ fallback: "style-loader", use: "css-loader" }) }],
20170320更新
最终发现重复压缩错误的缘由是由于.min.css
文件中包含以下代码:
background-image: url('data:image/svg+xml;charset=utf-8,<svg viewBox=\'0 0 120 120\' xmlns=\'http://www.w3.org/2000/svg\' xmlns:xlink=\'http://www.w3.org/1999/xlink\'><defs><line id=\'l\' x1=\'60\' x2=\'60\' y1=\'7\' y2=\'27\' stroke=\'%236c6c6c\' stroke-width=\'11\' stroke-linecap=\'round\'/></defs><g><use xlink:href=\'%23l\' opacity=\'.27\'/><use xlink:href=\'%23l\' opacity=\'.27\' transform=\'rotate(30 60,60)\'/><use xlink:href=\'%23l\' opacity=\'.27\' transform=\'rotate(60 60,60)\'/><use xlink:href=\'%23l\' opacity=\'.27\' transform=\'rotate(90 60,60)\'/><use xlink:href=\'%23l\' opacity=\'.27\' transform=\'rotate(120 60,60)\'/><use xlink:href=\'%23l\' opacity=\'.27\' transform=\'rotate(150 60,60)\'/><use xlink:href=\'%23l\' opacity=\'.37\' transform=\'rotate(180 60,60)\'/><use xlink:href=\'%23l\' opacity=\'.46\' transform=\'rotate(210 60,60)\'/><use xlink:href=\'%23l\' opacity=\'.56\' transform=\'rotate(240 60,60)\'/><use xlink:href=\'%23l\' opacity=\'.66\' transform=\'rotate(270 60,60)\'/><use xlink:href=\'%23l\' opacity=\'.75\' transform=\'rotate(300 60,60)\'/><use xlink:href=\'%23l\' opacity=\'.85\' transform=\'rotate(330 60,60)\'/></g></svg>');
因此包含这种代码的css使用css-loader的minify时会报错,解决方法是暂时将这类的css单独放入文件中,而且不进行minify
说明:在将项目划分目录结构后,html内和css内都有引用img或font,采用html-loader
替换html内部资源,以后发现构建出来后的文件中,img和font等资源的引用路径不对。如:
原本应该是路径 ../img.***.img 结果直接就变成了 img/***.img 致使路径不一致
解决:默认打包路径没法替换为相对路径。这时候须要引入publicPath
这个变量,将全部的资源用全局路径替换,如:
output: { // 用来解决css中的路径引用问题 publicPath: config.publicPath, },
以上publicPath由开发者自身根据实际状况进行配置,通常是指向项目的发布路径根目录,好比http://localhost:8080/dist/
,能够自由切换开发模式和发布模式
webpack-dev-serve
配置错误带来的问题说明:在使用webpack-dev-serve
时遇到了以下问题:
one:
webpack-dev-server --port 8082
便可开启服务,而且自动监听进行刷新(而且支持iframe刷新与inline刷新)publicPath
后,默认的服务端配置,启动后不会自动监听进行刷新devServer
和构建的路径outputPath不一致致使的,如Project is running at http://localhost:8082/ webpack output is served from http://localhost:8080/dist/
//dev版才有serve devServer: { historyApiFallback: true, hot: false, //不使用inline模式,inline模式通常用于单页面应用开发,会自动将socket注入到页面代码中 inline: false, //content-base就是 codeResource -须要监听源码 contentBase: path.resolve(__dirname, config.codeResource), watchContentBase: true, // 默认的服务器访问路径,这里和配置中一致,须要提取成纯粹的host:ip public: /https?:\/\/([^\/]+?)\//.exec(config.publicPath)[1] },
two:
contentBase:"dist"
,可是却发现修改dist里的任何文件,服务端都不会刷新three:
inline
和hot
,可是热更新无效HotModuleReplacementPlugin
,须要以下声明new webpack.HotModuleReplacementPlugin()
four:
ERR_NAME_NOT_RESOLVED
,不能实时刷新,一直都没法找到缘由//正常设置 localhost:8080 //个人设置 http://localhost:8080
Project is running at http://http://localhost:8080/
,因此只须要改为正常配置便可iframe
刷新,inline和hot都要是falsefive:(20170322更新)
webpack-dev-server
默认只能在localhost访问,换为内网ip就不行了(好比192.×××,就算是本机也不行的)//这个配置能够运行其它机器访问 host: '0.0.0.0', //或者运行时 -- host 0.0.0.0
hash
与chunkhash
形成的问题说明:项目发布时,为了解决缓存,须要进行md5签名,这时候就须要用到hash
和chunkhash
等了,可是却遇到了以下问题:(hash系列问题的解决大多参考了参考来源中的博客)
one:(hash问题)
hash
对js和css进行签名时,每一次hash值都不同,致使没法利用缓存hash
字段是根据每次编译compilation的内容计算所得,也能够理解为项目整体文件的hash值,而不是针对每一个具体文件的。(因此每一次编译都会有一个新的hash,并不适用)chunkhash
(js和css要使用chunkhash),chunkhash
的话每个js的模块对应的值是不一样的(根据js里的不一样内容进行生成)two:(img的chunkhash问题)
chunkhash
,可是又有了新的问题-img和font等资源中,使用chunkhash
会报错chunkhash
只适用于js和css,img中是没有这种东西的,仍然须要用到hash
(这个hash有点区别,每个资源自己有本身的hash)three:(chunkhash重复问题)
chunkhash
是相同的,致使没法区分css和js的更新,以下index2-ddcf83c3b574d7c94a42.css index2-ddcf83c3b574d7c94a42.js
*解决:css是使用ExtractTextPlugin
插件引入的,这时候可使用到这个插件提供的contenthash
,以下(使用后css就有独立于js外的指纹了),
new ExtractTextPlugin("[name]-[contenthash].css")
chunkhash
变更(缘由估计是webpack内置的算法变为了只计算js chunk),因此css请务必使用contenthash
,不然修改后没法生成新的签名,而是会覆盖之前的资源UNMET PEER DEPENDENCY node-sass
,依赖包安装失败说明:刚开始试了下,sass的编译,里面有引入node-sass
这个依赖包,以后基于这个出现了一些问题
one:(安装node-sass
失败)
sass
时,依赖了这个包,可是用npm安装时,安装失败cnpm
安装,安装cnpm以下npm install -g cnpm --registry=https://registry.npm.taobao.org
two:(node-sass
引发的其它安装包安装失败)
+-- UNMET PEER DEPENDENCY node-sass@^4.0.0 -- webpack-dev-server@2.4.1 extraneous
sourceMap
配置带来的问题说明:在使用sourceMap时,遇到了如下问题
one:(uglify压缩去掉了sourceMap)
sourceMap:true,
sourceMapFilename:'maps/[name].map'
,将map文件放入maps文件夹中htmlPagePluginConfig
配置带来的问题20170318更新
说明: 同时引入了html-loader
和html-webpack-plugin
后,两个插件都设置了minify属性,则会编译生成时报错,错误配置以下:
loader: 'html-loader', options: { minimize: config.isRelease ? true : false, } new HtmlWebpackPlugin({ *** minify: config.isRelease ? { collapseWhitespace: true, collapseBooleanAttributes: true, removeComments: true, removeEmptyAttributes: true, removeScriptTypeAttributes: true, removeStyleLinkTypeAttributes: true, minifyJS: true, minifyCSS: true }: null, })
解决:只须要将HtmlWebpackPlugin中对应的minify属性去掉便可。
webpack
中JS手动引入的图片问题20170318更新
说明: webpack是万物皆模块,但也就是说,不经过require引入的就不会算成模块了(插件中的另算,那是处理过的)。因此,在JS中手动引入图片时会遇到问题就是对应的图片并不会被打包,致使以后找不到路径。以下:
var GalleryData = [{ id: "testgallery1", title: "", //为空 //保持目录结构 url: "../../static/img/gallery/img_testgallery1.jpg" }, { id: "testgallery2", title: "", //为空 url: "../../static/img/gallery/img_testgallery2.jpg" }];
以上的url就是引入的源码本地图片,可是却发现并不会被打包出来。
解决:
static
文件夹做为静态资源,用copy-webpack-plugin
插件提取出来(这时候须要遵照的一个约定就是static
文件夹下的是专门给js引入或者外部资源访问的,平时正常的css,html中的引入请放入其它文件夹中,好比img
,避免相互影响,这就是约定大于配置)var imgUrl = require('./images/bg.jpg'), imgTempl = '';
本次进行webpack学习时。依次安装功能递增,按部就班的写了多个demo(每个都可正常运行),每个demo都有自身的READEME.MD
说明,目录结构以下;
├── 01helloWorld # 入门hellworld,一个html,一个js,一个css,css默认嵌入在js中,html采用`HtmlWebpackPlugin`加载 ├ ├── 02helloWorld2 # 基于第1个进行拓展,css使用`ExtractTextPlugin`单独打包成一个文件 ├ ├── 03pageWithSingleJsAndCss # 基于第2个进行拓展,示例页面由一个变为多个,而且抽取了通用配置文件`common.config` ├ ├── 04pageWithStaticResource # 基于第3个进行拓展,增长了`html-loader`替换静态资源,解决了css重复压缩报错问题,使用`publicPath`,解决资源文件引用路径问题,增长了`webpack-dev-server`配置 ├ ├── 05withCommonChunk # 基于第4个进行拓展,增长了`CommonsChunkPlugin`提取公告js和css,增长了`UglifyJsPlugin`,修改了一些配置,更好应用于项目 ├ ├── 06withHashStaticAndRelease # 基于第5个进行拓展,增长了`CopyWebpackPlugin`复制静态资源,增长了`chunkhash`,`contenthash`等指纹签名功能,增长了`alias`别名设置,增长了release版本和dev版本的开关 ├ ├── 07withLocalServer # 基于第6个进行拓展,增长了一个`api-server`,来写本地测试接口(已经进行了跨域配置) ├ └── 08withFamilyBucket # 基于第7个进行拓展,webpack全家桶项目,增长了`source-map`,增长了`assets-webpack-plugin`等等
系列demo的源码地址是: https://github.com/dailc/webpack-freshmanual
初次发布2017.03.13
于我的博客