编译es6:
基础:babel-loader --save-dev babel-core --save-dev;要配置babel以什么规范打包(针对语法)要用到babel-preset-env --save-dev,如es2015/es2016/es2017/env(2015-2017及最近),rules.use.options.presets:['env',{targets:{browsers: ['> 1%', 'last 2 versions']}}]。
babel-polyfill --save(在代码开始就要import进来)和babel-runtime --save、babel-plugin-transform-runtime --save-dev,(es的函数方法一些低版本浏览器还不具有,需要用到polyfill和runtime这两个babel插件)。(比如Generator Set Map Array.form Array.prototype.include都不会被babel处理),babel-polyfill为全局垫片(全局可以使用新函数方法)为应用准备(为自己所用),babel-runtime为局部垫片为框架(开发给别人用)准备。我们可以在根目录下.babelrc中配置babel。
提取公共代码:
主要针对多页面应用,减少代码冗余,提高加载速度(spa公共代码提前加载出来,非spa公共代码缓存起来)。
CommonsChunkPlugin
场景:单页应用、单页应用+第三发依赖、多页应用+第三发依赖+webpack生成代码
单页应用,commonsChunk是针对entry中多个入口文件(多页面应用)进行公共代码打包的,单入口(单页面应用)是无效的。
多页面应用,a1和a2都依赖b。在entry中把a1和a2都作为入口,就能把b单独打包出来成公共模块。
多页面应用+第三方依赖,
new webpack.optimize.SplitChunksPlugin({}) 或者optimization.splitChunk{()}
每个页面都要的公共代码提取出来后直接以script形式插入代码中而不进行http请求,html-webpack-inline-chunk-plugin,new HtmlInlinkChunkPlugin({ inlineChunks(指定要插入代码的模块名): ['mainifest'] })
代码分割和懒加载:
使用场景:分离业务代码和第三方依赖、分离业务代码和业务公共代码和第三方依赖、分离首次加载和访问后加载的代码。
实现方式一,webpack内置方法。
require.ensure(对原生promise有依赖,需要引入babel-polyfill)动态加载一个模块,参数:[],dependencies(依赖,加载进来并不会执行,其callback内还要通过require执行代码。当不指定依赖时,只在callback内require会变成异步);callback,回调函数里才会执行代码;chunkName(打包生产的模块名)。
require.include是针对两个子模块都引用了相同模块,当两个自模块都依赖了一个第三方模块,可以提前把第三个模块放到父模块中(比如page依赖pageA和pageB,而pageA/pageB依赖module,那么module不会被打包进pageA/pageB,直接打包进page)。
实现方式二,ES2015 Loader spec。
important替代require.ensure,important进来就已经执行,这点和require.ensure不同。important(/*webpackChunkName: async-chunk-name*/ /*webpackMode: lazy*/ modulename).then(...)(需要引入babel-polyfill),既符合es6语法,又实现代码分割懒加载功能。若两个important写了相同的webpackChunkName则打包文件会合并到这个chunk里。
注意:使用import报错的话。npm install --save-dev babel-plugin-syntax-dynamic-import。.babelrc 中加上插件"plugins": ["syntax-dynamic-import"]。
处理css:
如何通过loader引入css文件?
如何做到css模块化,不再是全局的?
如何通过loader去处理sass和less?
如何提取css代码?把css提取出一个单独文件,他会有自己的缓存,用到这个样式的多个文件,在第一个文件就已经缓存住了,接下来文件速度更快。
如何提取公共css代码?
1、style-loader是用来创建style标签,把提取出来的css放入html的style标签中,options: insertAt(插入位置)、insertInto(插入到dom,如:'#app')、singleton(是否只使用一个style标签,true就进行合并到一个style中,因为像ie有style个数标签限制)、transform(路径.js,浏览器环境下在把css插入html前运行,比如在此时我们可以根据浏览器不同类型做不同操作,会在每一个css文件插入前都执行一遍)。
另外:style-loader/url(在页面中创建link标签,一般不用)。style-loader/useable(import a from 'xx.css'后,可以通过在js中写a.use(),a.unues()来改变这段css引入或去掉)。
2、css-loader是解决在js中可以import css 进来。options:alias(解析的别名,当你匹配到的路径下的css里面你要import另外一个css时,alias在import的路径中可以生效)。importLoader(@import,是否生效,取决于css-loader后面是否还有其他loader)。Minimize(boolean,是否压缩css)。modules(boolean,是否启用css模块化)。
css模块化的语法,':local':局部样式;':global':全局样式;'compose':继承样式;'compose....from path':从某个文件引入样式。
3、配置Sass/Less。Less: npm install less-loader less --save-dev。Sass: npm install sass-loader node-sass --save-dev。
sass-loader、 node-sass,css预编译. 执行顺序是 sass-loader 》postcss-loader 》css-loader 》 style-loader,loaders是从下往上执行的,
4、提取css。extract-text-webpack-plugin 或者 extract-loader,我们用前者。1、匹配sass时用ExtractTextPlugin.extract({fallbak(提取出来之后):{loader:'style-loader'},use:[提取之前处理 ..]}) 。2、plugins中new ExtractTextWebpackPlugin({ filename:(提取出的css叫什么[name].min.css) ,allChunks: false (异步加载的JS模块中引入的css/sass/lss最终都会被打包进js模块中,并且能参与公共代码分割等)})。
5、postCss。postcss、postcss-loader、autoprefixer、cssnano(优化压缩css,css-loader已经集成了这个功能,minmize:true即可)、postcss-cssnext(可以使用css新语法如css 变量(variable), 自定义选择器(custom selectors),动态计算calc() )。autoprefixer使用:{loader: 'postcss-loader', options: {ident: 'postcss'(表明接下来插件是给postcss用的), plugins: [ require('autoprefixer')() ]}}
另外,postcss-import(帮助我们把通过@import引入的文件内容取到我们的css中,取过来时相对路径会变化,要配合postcss-url帮忙转换。另外还有postcss-assets。)
想要所有插件都共用一份浏览器适配配置,1、可以在package.json中配置。2、可以在项目根目录建一个.browserslistrc文件进行配置。
Tree Shaking:
对用不到的代码,打包时进行删除。使用场景:1、常规优化自己代码。2、引入第三方库代码。包括 js tree shaking和 css tree shaking。
js tree shaking: webpack打包时会把没有用到的方法标识出来,通过插件 uglifyjs-webpack-plugin 或者 webpack.optimize.uglifyJs(不支持es6)来删除它们。但有些第三方库比如Lodash不是以export方式输出代码块的,我们不能进行删减,我们需要借助一些插件,比如lodash需要下载一个 babel-plugin-lodash ,在babel-loader的options中配置{present: ['env'], plugins: ['lodash']。
问题:Babel默认将ES6模块通过commonJs模块转换输出,此时利用ES6模块的tree-shaking就不灵了。
方法:babel-preset-env有个modules的配置项就是控制这个的,把它设置成false就不会把ES6模块转换成commonJs了。
css tree shaking:需要用到 purifycss-webpack glob-all(其中有glob.sync可以用来多路径同时加载)。该插件必须放在css提取插件extractTextWebpackPlugin插件后面。new PurifyCss({ path: glob.sync([ path.join(_dirname, 'app/html/*.html'), path.join(_dirname, 'app/js/*.js') ]) })
文件处理:
1、如何引入图片,引入图片后webpack如何处理图片。2、合成雪碧图。2、压缩图片。3、小图片不需要压缩,进行base64编码。
url-loader/file-loader +img-loader +postcss-sprites
处理图片:file-loader(我们css中写的路径是相对于css的,而打包后文件路径是相对于入口html文件的,file-loader主要处理文件路径问题) options: {publicPath(处理过图片路径前一起加一段路径):'',outputPath(图片打包输出文件路径):' ',useRelativePath(打包出文件路径是否使用相对与此配置文件的相对路径): true,name(打包后输出文件名name): '[name].min.[ext]'}
图片base64编码:对小图片进行base64编码减少http请求:url-loader(和file-loader功能差不多就多了个base64编码,打包出的图片文件名可以在url-loader/file-loader中配置name:[name]-[hsah:5].[ext]),options:{ limit(对小于这个值大小图片进行base64编码): 10000,其他同file-loader一样,可以替代file-loader }
压缩图片:img-loader ,options: {pngquant: { quality(图片质量控制): 80 }}
合成雪碧图:postcss-sprites 在postcss-loader中 options: { ident: 'post', plugins: [ require('postcss-sprites')( { spritePath(雪碧图输出路径): ' dist/.. ' ,retina: true} ) ] }。设计师提供2倍大小图片高清适配,那么2倍大小图片如何做雪碧图?1、设置retina:true,2、告诉postcss-sprites哪些屏幕是retina图片,即在图片名后面加上@2x
处理字体文件:先把字体文件下载放到项目中,css中@font-face{font-family(自定义字体名): '..' src: url('字体文件路径') }注册, 最后在css中使用 它就好了。url-loader
处理第三方库:webpack.ProvidePlugin 、imports-loader 、 window 命名空间。需要在每个模块中都引入一段代码,1、若远程cdn上的第三方库,直接在页面