webpack(v3.*)javascript
一、webpack介紹css
webpack官網:https://webpack.js.org/
webpack中文官網:https://doc.webpack-china.org...
webpack打包工具源代碼:https://github.com/webpack/we...html
二、初始化項目vue
cd yourproject npm init //生成package.json文件 npm install webpack --save-dev
三、webpack.config.js配置文件html5
(1)、context:上下文,這裏省略了,默認爲當前文件模塊的絕對路徑,下面的entry和output中的路徑都是相對於context上下文的相對路徑.java
(2)、output屬性:(v3.10.0版本要求path是絕對路徑,須要使用node.js的path模塊)node
注意: path.resolve方法用於將相對路徑轉爲絕對路徑。react
var path = require("path"); //使用前引入path模塊 module.exports = { entry: './src/js/main.js', output: { filename: 'bundle.js', path: path.resolve(__dirname, './dist/js'), publicPath: "https://cdn.example.com/" //用publicPath配置打包後生成線上地址 } }
注意: publicPath,當咱們須要上線的時候設置此屬性,最後打包的文件路徑會被替換爲publicPath設置的地址值。webpack
注意: filename: '[name]-[chunkhash].js',filename使用佔位符確保每一個文件具備惟一的名稱。同時使用chunkhash能夠達到控制文件版本號的做用,這點與gulp是相通的原理。因此,一旦文件作了修改,再執行webpack,則更改過的文件的chunkhash會發生改變,未作改動的文件的chunkhash不變。git
(3)、plugins屬性
介紹:plugins 是一個數組,裏面是實例化的plugin,即new HtmlWepackPlugin({//code}),這種形式。
① html-webpack-plugin插件:該插件用於生成一個HTML5文件,這個文件用script標籤引用全部webpack包。(https://www.npmjs.com,npm官網...
//安裝 npm install html-webpack-plugin --save-dev //webpack.config.js配置文件中引入 var HtmlWepackPlugin = require("html-webpack-plugin"); //設置配置項 plugins: [ new HtmlWepackPlugin({ filename:'index-[hash].html', //輸出文件名稱 template:'index.html', //模板路徑 inject:"head", //值:body,head,false;script和link文件注入body或head中,或者false不注入。 chunks:["index","common"], //容許插入到模板中的一些chunk,不配置此項默認會將entry中全部的chunk注入到模板中。多頁應用配置多個頁面時,每一個頁面注入的thunk應該是不相同的,須要經過該配置爲不一樣頁面注入不一樣的thunk. excludeChunks: ["constan"], //這個與chunks配置項正好相反,用來配置不容許注入的thunk。 showErrors: true, //值:true/false,默認true;是否將錯誤信息輸出到html頁面中。這個頗有用,在生成html文件的過程當中有錯誤信息,輸出到頁面就能看到錯誤相關信息便於調試。 title:"MyApp", //須要在引用template模板中調用此變量 minify: { //壓縮代碼 collapseWhitespace: true, //刪除空格 html5: true } }) ]
注意: title屬性的坑:var HtmlWebpackPlugin = require('html-webpack-plugin'); 這個變量隨意。可是在模板中<title><%= htmlWebpackPlugin.options.title %></title>必須使用駝峯式命令。否則會報錯一直提示這個插件未定義。
注意: 在頁面中引入inline的script方法以下:
在github上,https://github.com/jantimon/h...。共用的main.js以inline的形式引進,a.js,b.js,c.js之外鏈的形式引進.模板index.html中,
首先在<head>中:
<script type="text/javascript"> <%= compilation.assets[htmlWebpackPlugin.files.chunks.main.entry.substr(htmlWebpackPlugin.files.publicPath.length)].source() %> </script>
重點:!!!compilation.assets是webpack暴露出來能夠獲取文件數據的方法。經過傳文件名路徑進這個對象,拿到這個文件的索引,經過調用source拿到文件內容。
compilation.assets須要的是不帶publicPath,htmlWebpackPlugin.files.chunks.main.entry帶publicPatch,因此用substr()截取。
而後在<body>中:
<%= htmlWebpackPlugin.files.chunks[k].entry %>
最後在webpack.config.js中: inject屬性設置爲false便可。
(4)、loader屬性(以babel-loader爲例,用babel-loader將js文件轉義爲瀏覽器可識別的js)
module:{ rules:[ //模塊規則 { test: /\.js$/, //正則匹配 use: [{ loader:'babel-loader', options:{ presets: ["env"] //採用babel-loader的"env"規則將找的es6,es7,es5語法轉碼爲瀏覽器可識別的js } }], include: [ path.resolve(__dirname, "/src") //指定babel-loaders尋找的文件路徑,注意需是絕對路徑 ], exclude: [ path.resolve(__dirname, "/node_modules/") //排除node_modules文件下js,注意需是絕對路徑 ] } ] },
注意: webpack官網介紹到:「Rule.loader is a shortcut to Rule.use: [ { loader } ]」. 即下圖:
(5)、loader屬性(css處理的loader)(postcss參考文章:https://segmentfault.com/a/11...
在web開發中瀏覽器兼容問題,咱們不得不使用兼容性前綴,less語言在編譯時能夠補全css代碼的兼容性前綴,可是針對css文件不全前綴須要使用postcss-loader。以下圖:
在common.css中引入其餘的css文件:
在app.js入口文件中引入common.css,這樣打包的時候就能將css文件進行打包:
(6)、wbpack-dev-server
//首先安裝插件 npm i webpack-dev-server --save-dev npm i cross-env --save-dev npm i html-webpack-plugin --save-dev
package.json文件:
"scripts":{ //prod環境 "build": "cross-env NODE_ENV=production webpack --config webpack.config.js", //dev環境 "dev": "cross-env NODE_ENV=development webpack-dev-server --config webpack.config.js" }
webpack.config.js文件:
const path = require("path") const HTMLWebapckPlugin = require("html-webpack-plugin") const webpack = require('webpack') //引入webpack //在package.json中的「NODE_ENV=development」,可經過下面的process.env讀到變量NODE_ENV const isDev = process.env.NODE_ENV === "development" const config = { target:"web",//web平臺 entry: path.join(__dirname,'src/index.js'), output:{ filename:'bundle.js', path:path.join(__dirname,"dist") }, module:{ rules:[ { test:/\.vue$/, loader:'vue-loader' }, { test:/\.css$/, use:[ 'style-loader', 'css-loader' ] }, { test:/\.(gif|jpg|jpeg|png|svg)$/, use:[ { loader:'url-loader', options:{ limit:1024, name:'[name]-[hash].[ext]' } } ] } ] }, plugins:[ //使用Vue、react框架時須要DefinePlugin這的插件,由於框架會根據不一樣環境打包依賴,因此要區分環境從而選擇不一樣的依賴 new webpack.DefinePlugin({ //定義環境變量,對應上面的isDev判斷 'process.env':{ NODE_ENV:isDev ? '"development"' : '"production"' //注意此處單引號內還須要雙引號 } }), //生成HTML頁面 new HTMLWebapckPlugin() ] } //dev環境 if(isDev){ //經過devtool對代碼進行映射,能夠在瀏覽器端能夠調試 config.devtool = "#cheap-module-eval-sourve-map" //devserver 是在webpack2之後纔出現的 config.devServer = { port:'8020', //端口號 host:"0.0.0.0", //設置成這樣後,移動端也能夠通IP訪問頁面 //webpack編譯時任何錯誤顯示在瀏覽器中 overlay:{ errors:true, }, open:true,//自動打開瀏覽器 hot:true //webpack功能:再也不從新刷新整個頁面,而是局部更新,即熱更新 } config.plugins.push( new webpack.HotModuleReplacementPlugin(), //搭配hot:true一塊兒使用 new webpack.NoEmitOnErrorsPlugin() //搭配hot:true一塊兒使用,去除一些不須要展現的信息 ) } module.exports = config
執行npm run dev 就能夠經過localhost:8020打開頁面
(7)、webpack單獨打包css文件
//安裝依賴 npm i extract-text-webpack-plugin
在webpack.config.js文件中引用:(結合6中的配置文件)
//dev環境 if(isDev){ config.module.rules.push( { test:/\.scss$/, use:[ 'style-loader', 'css-loader', { loader:'postcss-loader', options:{ sourceMap:true } }, 'sass-loader' ] } ) config.devtool = "#cheap-module-eval-sourve-map" //devserver 是在webpack2之後纔出現的 config.devServer = { port:'8020', //端口號 host:"0.0.0.0", //設置成這樣後,移動端也能夠通IP訪問頁面 //webpack編譯時任何錯誤顯示在瀏覽器中 overlay:{ errors:true, }, open:true,//自動打開瀏覽器 hot:true //熱更新 } config.plugins.push( new webpack.HotModuleReplacementPlugin(), new webpack.NoEmitOnErrorsPlugin() ) }else{ //正式環境 config.output.filename='[name].[chunkhash:8].js' //正式環境使用chunkhash,dev環境不能使用chunkhash,可以使用hash. config.module.rules.push({ test:/\.scss$/, use:ExtractTextWebpack.extract({ fallback:'style-loader', use:[ 'css-loader', { loader:'postcss-loader', options:{ sourceMap:true } }, 'sass-loader' ] }) }) config.plugins.push( new ExtractTextWebpack('style.[contentHash:8].css') ) }
注意:vue組件中的css樣式是不會打包到上面的style.[contentHash:8].css文件中的,由於他是異步加載的。
(8)、單獨打包類庫文件及hash
將類庫代碼和業務代碼分離打包,利用瀏覽器長期的緩存類庫代碼。
//正式環境配置 { config.entry = { //業務邏輯代碼 app:path.join(__dirname,"src/index.js"), //類庫代碼在此聲明,此處以Vue框架爲例 vendor: ['vue'] } config.output.filename='[name].[chunkhash:8].js', config.module.rules.push({ test:/\.scss$/, use:ExtractTextWebpack.extract({ fallback:'style-loader', use:[ 'css-loader', { loader:'postcss-loader', options:{ sourceMap:true } }, 'sass-loader' ] }) }), config.plugins.push( new ExtractTextWebpack('style.[contentHash:8].css'), //單獨打包,app中就不會出現類庫代碼,必須放在runtime以前 new webpack.optimize.CommonsChunkPlugin({ //name屬性值要和上面定義的vendor一致 name:'vendor' }), new webpack.optimize.commonsChunkPlugin({ name:'runtime' }) ) }
hash與chunkhash區別:
hash:打包的全部文件共用的一個值 chunkhash:打包的不一樣的塊擁有不一樣的chunkhash,因此正式環境應使用chunkhash,這樣能夠保證類庫文件不會再每次更改業務從新打包後,又擁有一個新的hash值,而是一直使用以前的chunkhash,這樣瀏覽器就不會在去下載那些依賴,從而實現了緩存。 詳細請見:https://www.imooc.com/article/21538