Webpack常見靜態(tài)資源處理-模塊加載器(Loaders)+ExtractTextPlugin插件
webpack系列目錄
webpack 系列 三:webpack 如何集成第三方j(luò)s庫(kù)
webpack 系列 四:webpack 多頁(yè)面支持 & 公共組件單獨(dú)打包
webpack 系列 五:webpack Loaders 模塊加載器
webpack 系列 六:前端項(xiàng)目模板-webpack+gulp實(shí)現(xiàn)自動(dòng)構(gòu)建部署
基于webpack搭建純靜態(tài)頁(yè)面型前端工程解決方案模板, 最終形態(tài)源碼見github: https://github.com/ifengkou/webpack-template
正文
Webpack將所有靜態(tài)資源都認(rèn)為是模塊,比如JavaScript,CSS,LESS,TypeScript,JSX,CoffeeScript,圖片等等,從而可以對(duì)其進(jìn)行統(tǒng)一管理。為此Webpack引入了加載器的概念,除了純JavaScript之外,每一種資源都可以通過對(duì)應(yīng)的加載器處理成模塊。和大多數(shù)包管理器不一樣的是,Webpack的加載器之間可以進(jìn)行串聯(lián),一個(gè)加載器的輸出可以成為另一個(gè)加載器的輸入。比如LESS文件先通過less-load處理成css,然后再通過css-loader加載成css模塊,最后由style-loader加載器對(duì)其做最后的處理,從而運(yùn)行時(shí)可以通過style標(biāo)簽將其應(yīng)用到最終的瀏覽器環(huán)境。
一 常用loader
安裝css/sass/less loader加載器
cnpm install file-loader css-loader style-loader sass-loader ejs-loader html-loader jsx-loader image-webpack-loader --save-dev
webpack.config.js配置:
module: { loaders: [ { test: /\.((woff2?|svg)(\?v=[0-9]\.[0-9]\.[0-9]))|(woff2?|svg|jpe?g|png|gif|ico)$/, loaders: [ // 小于10KB的圖片會(huì)自動(dòng)轉(zhuǎn)成dataUrl 'url?limit=10240&name=img/[hash:8].[name].[ext]', 'image?{bypassOnDebug:true, progressive:true,optimizationLevel:3,pngquant:{quality:"65-80",speed:4}}' ] }, { test: /\.((ttf|eot)(\?v=[0-9]\.[0-9]\.[0-9]))|(ttf|eot)$/, loader: 'url?limit=10000&name=fonts/[hash:8].[name].[ext]' }, {test: /\.(tpl|ejs)$/, loader: 'ejs'}, {test: /\.css$/, loader: 'style-loader!css-loader'}, { test: /\.scss$/, loader: 'style!css!sass'} ] },
index.html 新增兩個(gè)div
<div class="small-webpack"></div> <div class="webpack"></div>
index.css 增加兩個(gè)圖片,同時(shí)將webpack.png(53kb) 和 small-webpack.png(9.8k)
.webpack { background: url(../img/webpack.png) no-repeat center; height:500px; } .small-webpack { background: url(../img/small-webpack.png) no-repeat center; height:250px; }
index.js 引入css
require('../css/index.css');
執(zhí)行webpack指令
$ webpack
查看生成的目錄結(jié)構(gòu)
其中并沒有css文件,css被寫入到了index.js中,index.js 部分截圖
總結(jié):
圖片采用了url-loader加載,如果小于10kb,圖片則被轉(zhuǎn)化成 base64 格式的 dataUrl
css文件被打包進(jìn)了js文件中
css被打包進(jìn)了js文件,如果接受不了,可以強(qiáng)制把css從js文件中獨(dú)立出來(lái)。官方文檔是以插件形式實(shí)現(xiàn):文檔docs點(diǎn)這,插件的github點(diǎn)這
二:extract-text-webpack-plugin 插件介紹
Extract text from bundle into a file.從bundle中提取出特定的text到一個(gè)文件中。使用 extract-text-webpack-plugin就可以把css從js中獨(dú)立抽離出來(lái)
安裝
$ npm install extract-text-webpack-plugin --save-dev
使用(css為例)
var ExtractTextPlugin = require("extract-text-webpack-plugin"); module.exports = { module: { loaders: [ { test: /\.css$/, loader: ExtractTextPlugin.extract("style-loader", "css-loader") } ] }, plugins: [ new ExtractTextPlugin("styles.css") ] }
它將從每一個(gè)用到了require("style.css")的entry chunks文件中抽離出css到單獨(dú)的output文件
API
new ExtractTextPlugin([id: string], filename: string, [options])
- id Unique ident for this plugin instance. (For advanded usage only, by default automatic generated)
- filename the filename of the result file. May contain [name], [id] and [contenthash].
- [name] the name of the chunk
- [id] the number of the chunk
- [contenthash] a hash of the content of the extracted file
- options
- allChunks extract fromall additional chunks too (by default it extracts only from the initial chunk(s))
- disable disables the plugin
ExtractTextPlugin.extract([notExtractLoader], loader, [options])
根據(jù)已有的loader,創(chuàng)建一個(gè)提取器(loader的再封裝)
- notExtractLoader (可選)當(dāng)css沒有被抽離時(shí),加載器不應(yīng)該使用(例如:當(dāng)allChunks:false時(shí),在一個(gè)additional 的chunk中)
- loader 數(shù)組,用來(lái)轉(zhuǎn)換css資源的加載器s
- options
- publicPath 重寫該加載器(loader)的 publicPath 的設(shè)置
多入口文件的extract的使用示例:
let ExtractTextPlugin = require('extract-text-webpack-plugin'); // multiple extract instances let extractCSS = new ExtractTextPlugin('stylesheets/[name].css'); let extractLESS = new ExtractTextPlugin('stylesheets/[name].less'); module.exports = { ... module: { loaders: [ {test: /\.scss$/i, loader: extractCSS.extract(['css','sass'])}, {test: /\.less$/i, loader: extractLESS.extract(['css','less'])}, ... ] }, plugins: [ extractCSS, extractLESS ] };
三:改造項(xiàng)目-抽離css
安裝插件到項(xiàng)目
npm install extract-text-webpack-plugin --save-dev
配置webpack.config.js,加入ExtractTextPlugin和相關(guān)處理:
var webpack = require("webpack"); var path = require("path"); var srcDir = path.resolve(process.cwd(), 'src'); var nodeModPath = path.resolve(__dirname, './node_modules'); var pathMap = require('./src/pathmap.json'); var glob = require('glob') var CommonsChunkPlugin = webpack.optimize.CommonsChunkPlugin; var HtmlWebpackPlugin = require('html-webpack-plugin'); var ExtractTextPlugin = require('extract-text-webpack-plugin'); var entries = function () { var jsDir = path.resolve(srcDir, 'js') var entryFiles = glob.sync(jsDir + '/*.{js,jsx}') var map = {}; for (var i = 0; i < entryFiles.length; i++) { var filePath = entryFiles[i]; var filename = filePath.substring(filePath.lastIndexOf('\/') + 1, filePath.lastIndexOf('.')); map[filename] = filePath; } return map; } var html_plugins = function () { var entryHtml = glob.sync(srcDir + '/*.html') var r = [] var entriesFiles = entries() for (var i = 0; i < entryHtml.length; i++) { var filePath = entryHtml[i]; var filename = filePath.substring(filePath.lastIndexOf('\/') + 1, filePath.lastIndexOf('.')); var conf = { template: 'html!' + filePath, filename: filename + '.html' } //如果和入口js文件同名 if (filename in entriesFiles) { conf.inject = 'body' conf.chunks = ['vendor', filename] } //跨頁(yè)面引用,如pageA,pageB 共同引用了common-a-b.js,那么可以在這單獨(dú)處理 //if(pageA|pageB.test(filename)) conf.chunks.splice(1,0,'common-a-b') r.push(new HtmlWebpackPlugin(conf)) } return r } var plugins = []; var extractCSS = new ExtractTextPlugin('css/[name].css?[contenthash]') var cssLoader = extractCSS.extract(['css']) var sassLoader = extractCSS.extract(['css', 'sass']) plugins.push(extractCSS); plugins.push(new CommonsChunkPlugin({ name: 'vendor', minChunks: Infinity })); module.exports = { entry: Object.assign(entries(), { // 用到什么公共lib(例如jquery.js),就把它加進(jìn)vendor去,目的是將公用庫(kù)單獨(dú)提取打包 'vendor': ['jquery', 'avalon'] }), output: { path: path.join(__dirname, "dist"), filename: "[name].js", chunkFilename: '[chunkhash:8].chunk.js', publicPath: "/" }, module: { loaders: [ { test: /\.((woff2?|svg)(\?v=[0-9]\.[0-9]\.[0-9]))|(woff2?|svg|jpe?g|png|gif|ico)$/, loaders: [ //小于10KB的圖片會(huì)自動(dòng)轉(zhuǎn)成dataUrl, 'url?limit=10000&name=img/[hash:8].[name].[ext]', 'image?{bypassOnDebug:true, progressive:true,optimizationLevel:3,pngquant:{quality:"65-80",speed:4}}' ] }, { test: /\.((ttf|eot)(\?v=[0-9]\.[0-9]\.[0-9]))|(ttf|eot)$/, loader: 'url?limit=10000&name=fonts/[hash:8].[name].[ext]' }, {test: /\.(tpl|ejs)$/, loader: 'ejs'}, {test: /\.css$/, loader: cssLoader}, {test: /\.scss$/, loader: sassLoader} ] }, resolve: { extensions: ['', '.js', '.css', '.scss', '.tpl', '.png', '.jpg'], root: [srcDir, nodeModPath], alias: pathMap, publicPath: '/' }, plugins: plugins.concat(html_plugins()) }
其中,用ExtractTextPlugin 來(lái)抽離css
var ExtractTextPlugin = require('extract-text-webpack-plugin'); var extractCSS = new ExtractTextPlugin('css/[name].css?[contenthash]') var cssLoader = extractCSS.extract(['css']) var sassLoader = extractCSS.extract(['css', 'sass']) plugins.push(extractCSS); ...... //conf - module - loaders {test: /\.css$/, loader: cssLoader}, {test: /\.scss$/, loader: sassLoader}
注意事項(xiàng):
css中img的路徑會(huì)出現(xiàn)問題,通過設(shè)置publicPath 解決,采用絕對(duì)路徑
output: { ...... publicPath: "/" },
運(yùn)行:
$ webpack
期望
- css單獨(dú)抽離,打包成單獨(dú)的css文件
- html自動(dòng)引用css文件
- 小于10k的圖片,轉(zhuǎn)成base64 格式的 dataUrl
- webpack.png 會(huì)被壓縮,減少文件大小
運(yùn)行webpack后的項(xiàng)目的目錄結(jié)構(gòu):
生成的 dist/index.html 自動(dòng)引用了 index.css 和相關(guān)的js,由于設(shè)置了publicPath 所以相應(yīng)的鏈接都采用了絕對(duì)路徑
生成的 dist/index.css 小圖片被轉(zhuǎn)成了data:image形式:
結(jié)果:
- css單獨(dú)打包到css目錄
- html自動(dòng)注入了link 標(biāo)簽
- small-webpack.png 小于10k,被打包進(jìn)了index.css
- webpack.png 由原來(lái)的50+k 被壓縮成 10- k
最后,運(yùn)行 webpack-dev-server 看一下運(yùn)行結(jié)果:
總結(jié)
Webpack將所有靜態(tài)資源都認(rèn)為是模塊,而通過loader,幾乎可以處理所有的靜態(tài)資源,圖片、css、sass之類的。并且通過一些插件如extract-text-webpack-plugin,可以將共用的css抽離出來(lái)
下篇介紹改進(jìn)webpack.config.js:
- 區(qū)分開發(fā)環(huán)境和生產(chǎn)環(huán)境
- 集成 gulp 實(shí)現(xiàn)自動(dòng)構(gòu)建打包部署
- github 發(fā)布 前端自動(dòng)化構(gòu)建的項(xiàng)目模板
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
JavaScript獲取XML數(shù)據(jù)附示例截圖
這篇文章主要介紹了JavaScript獲取XML數(shù)據(jù)的方法,需要的朋友可以參考下2014-03-03用Javascript數(shù)組處理多個(gè)字符串的連接問題
小技巧 用Javascript數(shù)組處理多個(gè)字符串的連接問題,大家可以參考下。2009-08-08讓textarea自動(dòng)調(diào)整大小的js代碼
讓textarea自動(dòng)調(diào)整大小的js代碼,需要的朋友可以參考下。2011-04-04npm?install報(bào)錯(cuò)Error:EPERM:operation?not?permitted,rename解決
這篇文章主要給大家介紹了關(guān)于npm?install報(bào)錯(cuò)Error:EPERM:operation?not?permitted,rename的解決辦法,文中介紹了可能遇到的多種原因以及解決辦法,需要的朋友可以參考下2024-01-01簡(jiǎn)述JavaScript提交表單的方式 (Using JavaScript Submit Form)
這篇文章主要介紹了簡(jiǎn)述JavaScript提交表單的方式 (Using JavaScript Submit Form)的相關(guān)資料,需要的朋友可以參考下2016-03-03JS讀取XML文件數(shù)據(jù)并以table形式顯示數(shù)據(jù)的方法(兼容IE與火狐)
這篇文章主要介紹了JS讀取XML文件數(shù)據(jù)并以table形式顯示數(shù)據(jù)的方法,涉及javascript針對(duì)xml節(jié)點(diǎn)操作及HTML表格操作的相關(guān)技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2016-06-06淺析script標(biāo)簽中的defer與async屬性
最近在網(wǎng)上看到一個(gè)前輩在寫script標(biāo)簽的時(shí)候,居然同時(shí)寫了async和defer屬性,想著這是什么意思呢?所以決定深入的了解下這其中的學(xué)問,以下這篇文章就是個(gè)人在學(xué)習(xí)了之后的一些總結(jié)分析,有需要的朋友們可以參考借鑒,下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧。2016-11-11微信小程序基于slider組件動(dòng)態(tài)修改標(biāo)簽透明度的方法示例
這篇文章主要介紹了微信小程序基于slider組件動(dòng)態(tài)修改標(biāo)簽透明度的方法,可通過slider組件拖動(dòng)實(shí)現(xiàn)圖片透明度的改變功能,涉及微信小程序事件綁定、base64格式圖片載入及slider組件使用技巧,需要的朋友可以參考下2017-12-12