摘要:使用等預處理器編寫可以將你項目中的所有文件,處理成瀏覽器能識別的文件。測試打包基本的配置就完成了。修改處理文件執行順序是從右到左修改一下入口文件中的樣式引入打包測試完美通過。這時可以使用提供的配置來使引入文件的時候變得更加方便簡單。
本文正文鏈接
最近公司弄了個有150+頁面的項目,心想,終于有機會可以去學習webpack了,以前想學卻沒有實際項目去引導逼迫去學,現在終于領略到了webpack的強大了。
什么是webpack在前端的項目開發中,總有大量的頁面和樣式需要處理,而維護這些文件也成了頭疼的問題。
為了簡化開發,于是就有很多好的開發方式,如:
模塊化開發。每個功能模塊都分開成一個個獨立的組件,需要的時候再引入。
scss等預處理器。
使用pug, jade 更快編寫HTML。
...
這些方式確實可以大大提高開發效率,但是每種方式都有自己的打包方式,還有兼容性處理,如果純手動處理,必然會增加工作量。
但是,現在有了webpack,上述問題基本解決了,一個webpack就可以處理各種繁瑣的過程,給你一個清爽,快速的開發環境。
WebPack可以看做是模塊打包機:它做的事情是,分析你的項目結構,找到JavaScript模塊以及其它的一些瀏覽器不能直接運行的拓展語言(Scss,TypeScript等),并將其轉換和打包為合適的格式供瀏覽器使用。
簡單的來說,在項目開發中,
你可以使用js,es6/7,甚至ts開發。
es6/es7, .ts => .js
使用stylus, scss, less 等預處理器編寫css
.scss/.less => .css
webpack可以將你項目中的所有文件,處理成瀏覽器能識別的文件。
開始使用webpack先新建一個練手用的空文件夾 $ mkdir webpack-demo ,并進入該文件夾。
新建 package.json.
$ npm init
安裝webpack及其基本插件。
$ npm i -D webpack extract-text-webpack-plugin html-webpack-plugin css-loader file-loader style-loader url-loader
其中:
extract-text-webpack-plugin : 該插件主要為了抽離css樣式,可以將css從打包的js中抽離出來。以link方式引入樣式。
html-webpack-plugin : 該插件主要是用于生成html文件,并可以根據入口文件來引入相應的文件。
css-loader : 解析css文件中的 import 和 require ,并處理他們。
style-loader : 將css樣式通過 style 標簽注入到html文件中。
file-loader : 指明webpack將所引入的對象,并返回一個公網能訪問的url地址。
url-loader : 將文件轉換成 base64編碼。
配置webpack。
新建一個配置文件: $ touch webpack.config.js
var webpack = require("webpack"); var path = require("path"); var ExtractTextPlugin = require("extract-text-webpack-plugin"); var HtmlWebpackPlugin = require("html-webpack-plugin"); var webpackConfig = { // 設置入口文件。 entry: "./src/js/index.js", output: { // 設置輸出文件夾 path: path.join(__dirname, "dist"), // 設置公用文件夾路徑 publicPath: "/", // 設置輸出的js文件的名字規則。 // [name] 為chunk中的名稱 // [hash] 為webpack生成的哈希值 filename: "js/[name].[hash].bundle.js" }, module: { rules: [{ // 處理css文件 test: /.css$/, loader: "style-loader!css-loader" }, { // 處理html文件,并處理img 中 src 和 data-src 的引入路徑 test: /.html$/, loader: "html-loader?attrs=img:src img:data-src" }, { // 處理字體文件 test: /.(woff|woff2|ttf|eot|svg)(?v=[0-9].[0-9].[0-9])?$/, loader: "file-loader?name=./fonts/[name].[ext]" }, { // 處理圖片,并將8k以下的圖片轉為base64編碼 test: /.(png|jpg|gif)$/, loader: "url-loader?limit=8192&name=./img/[hash].[ext]" }] }, plugins: [ // 公共js提取 new webpack.optimize.CommonsChunkPlugin({ name: "vendors", // 將公共模塊提取,生成名為`vendors`的chunk // minChunks: 3 // 提取至少3個模塊共有的部分 }), // 提取公共css樣式 new ExtractTextPlugin("./css/[name].css"), // 處理html文件。 new HtmlWebpackPlugin({ filename: "./view/index.html", //生成的html存放路徑,相對于path template: "./src/view/index.html", //html模板路徑 inject: "body", //js插入的位置,true/"head"/"body"/false hash: true, //為靜態資源生成hash值 // chunks: ["vendors", allDirs[i] + "/" + matches[1]], //需要引入的chunk,不配置就會引入所有頁面的資源 minify: { //壓縮HTML文件 removeComments: true, //移除HTML中的注釋 collapseWhitespace: false //刪除空白符與換行符 } }) ], // 設置開發服務器 devServer: { contentBase: path.join(__dirname, "dist/"), host: "localhost", port: 9090, inline: true } } module.exports = webpackConfig
測試配置文件:
先設置開發文件夾目錄:
- webpack-demo + node_modules - src + js // 存放js文件 + css // 存放css樣式 + view // 存放模板文件 webpack.config.js package.json
新建一個 html 文件: $ touch ./src/view/index.html。
Hello World Hello World
This is from webpack-demo
新建css文件: $ touch ./src/css/index.css。
h2{ color: red; opacity: 0.5; transform: rotateZ(-10deg); } p{ color: green; }
新建js文件: $ touch ./src/js/index.js。
// 引入css文件。 require("../css/index.css") console.log("hello world");
測試打包: $ webpack
OK!基本的配置就完成了。
我們可以看到,在項目中多了一個dist文件夾,里面存放的就是剛剛打包好的文件。打開index.html(需要在服務器中打開,并且服務器根目錄為dist)可以看到,生成的html文件,征程顯示我們寫的內容,css樣式則直接寫入了style標簽當中,而且自動引入了兩個js文件,其中,vendors是帶有公共部分的js文件,index則是我們一開始寫的js邏輯文件。
既然都用到了webpack自動打包了,那也順便使用webpack去處理scss文件(個人愛好是scss,less的處理同理),順便也處理完css中的其他兼容性問題和瀏覽器前綴問題吧(程序員的思維就是,懶)。
現在css中需要處理的有:
瀏覽器前綴和大部分兼容性問題: autoprefixer
flex 的兼容性問題: postcss-flexibility
opacity 兼容IE: postcss-opacity
顏色兼容性問題: postcss-color-rgba-fallback
scss文件處理: sass-loader 同時需要依賴 node-sass
壓縮css文件: cssnano
安裝上書postcss-loader的插件: $ npm i -D autoprefixer postcss-flexibility postcss-opacity postcss-color-rgba-fallback sass-loader node-sass
現在在webpack中處理css的問題,基本都是通過一個 postcss-loader 去完成所有的處理問題。
先新建一個文件夾,用于存放所有的scss文件: $ mkdir ./src/scss
再新建一個index.scss, $ touch ./src/scss/index.scss
body{ background: black; color: white; h2{ transform: translateX(10px) rotateZ(-10deg); color: red; opacity: 0.5; } }
將postcss的加載器中需要的多帶帶提取出來放在一個配置文件中: $ touch postcss.config.js
module.exports = { plugins: [ // minify css require("cssnano")({ preset: "default" }), // 處理css前綴 require("autoprefixer")({ browserslist: [ "> 1%", "last 2 versions", "Edge", "ie >= 9" ] }), // 處理flex瀏覽器兼容性 require("postcss-flexibility"), // 處理css中rgba顏色代碼 require("postcss-color-rgba-fallback"), // 處理css中opacity的IE兼容性。 require("postcss-opacity") ] }
修改 webpack.config.js:
var webpackConfig = { ... module: { rules: [{ // 處理css文件 test: /.(scss|sass|css)$/, // loader: "css-loader?importLoaders=1!postcss-loader!sass-loader", // loader執行順序是從右到左:sass-loader -> postcss-loader -> css-loader use: [ "style-loader", { loader: "css-loader", options: { // // 0 => no loaders (default); 1 => postcss-loader; 2 => postcss-loader, sass-loader importLoaders: 2 } }, "postcss-loader", "sass-loader" ] }, ... ] } ... } module.exports = webpackConfig
修改一下入口文件中的樣式引入: $ vim ./src/js/index.js
require("../scss/index.scss") console.log("hello world");
打包測試:
完美通過。
處理pug/jade文件項目有很多的頁面,而且頁面之間也有很多相同的頁面,之前寫慣了vue的組件,所以注冊我們也引入了pug作為前端模板引擎。 pug 的前身就是 jade ,所以語法什么都得基本都是一致的。具體的看 官網 。
和處理css的一樣,先要安裝加載器。 $ npm i -D pug pug-loader
新建一個簡單的頁面: $ touch ./src/view/index.pug
html title Test.html body h2 Welcome to pug. p This is from index.pug
修改一下配置文件中的html模板入口:
var webpackConfig = { ... plugins: [ // 公共js提取 new webpack.optimize.CommonsChunkPlugin({ name: "vendors", // 將公共模塊提取,生成名為`vendors`的chunk }), // 提取公共css樣式 new ExtractTextPlugin("./css/[name].css"), // 處理html文件。 new HtmlWebpackPlugin({ filename: "./view/index.html", //生成的html存放路徑,相對于path template: "./src/view/index.pug", //html模板路徑 inject: "body", //js插入的位置,true/"head"/"body"/false hash: true, //為靜態資源生成hash值 chunks: ["vendors", "index"], //需要引入的chunk,不配置就會引入所有頁面的資源 minify: { //壓縮HTML文件 removeComments: true, //移除HTML中的注釋 collapseWhitespace: false //刪除空白符與換行符 } }) ], ... } module.exports = webpackConfig
重新編譯打包:
在項目開發中,難免會遇到使用 es6 ,甚至 es7 去編寫js。但是大部分瀏覽器卻不支持這些語法,這時候,就需要 babel-loader 來處理js,并將其轉換為瀏覽器能識別的 es5 語法。
還是要安裝依賴: $ npm i -D babel-loader babel-core babel-preset-es2015
如果用上了es7 的語法,就要根據不同階段語法提案的轉碼規則(共有4個階段),選裝一個:
$ npm i -D babel-preset-stage-0 $ npm i -D babel-preset-stage-1 $ npm i -D babel-preset-stage-2 $ npm i -D babel-preset-stage-3
新建一個 .babelrc babel配置文件: $ touch .babelrc
{ "presets": ["es2015"], "plugins": [] }
修改 webpack 配置文件:
var webpackConfig = { ... module: { rules: [{ test: /.js$/, // 不編譯 node_modules 下的文件 exclude: /node_modules/, loader: "babel-loader" }] } ... } module.exports = webpackConfig
在 index.js 中寫個 es6 的語法:
require("../scss/index.scss") console.log("hello world"); ((message) => { console.log(message); })("message from es6") let step = 2; var add = number => number*=step console.log(add(2));
來,打包看看:
完美。
項目有多個頁面,每個頁面都對應著一個js入口和一個頁面,但是,入口 entry 和 html-webpack-plugin 每次只能配置一個具體的入口文件,如果每增加一個頁面就要去配置,那么這無形之中增加了工作量,因此,我們需要一個通用的入口文件。
既然在node中可以訪問文件夾并讀取其中的文件名,那么我們可以使用node來去循環讀取文件夾下的js文件,并自動添加至入口配置中:
新建一個config 文件夾,以存放webpack可變的配置,方便以后修改: $ mkdir config
因為遍歷入口文件都是一樣的操作流程,所以先寫一個工具包:$ touch config/utils.js
var fs = require("fs"); // 遞歸遍歷文件夾,獲取入口文件 function getAllFiles(dirRoot, type){ var filterReg = new RegExp("."+type+"$"); function getAllFileFromDir(root) { var res = [], files = fs.readdirSync(root) files.forEach((file) => { var pathname = root+"/"+file, state = fs.lstatSync(pathname) if (!state.isDirectory()) { // 過濾相對應的文件 filterReg.test(pathname) && res.push(pathname) // res.push(pathname.replace(dir_root+"/", "")) }else{ res = res.concat(getAllFileFromDir(pathname)) } }) return res } return getAllFileFromDir(dirRoot) } function getEntry(files, replaces){ var entry = {} for (var i = 0; i < files.length; i++) { var filename = files[i] replaces.map((replace) => { filename = filename.replace(replace, "") }) entry[filename] = files[i] } return entry } module.exports = { getAllFiles, getEntry }
再新建一個 js 入口文件配置: $ touch config/webpack.entry.js
var path = require("path"); var utils = require("./utils.js") var dir_root = path.resolve(__dirname, "../src/js"); // console.log(getAllFiles(dir_root)); var allFiles = utils.getAllFiles(dir_root, "js") var entry = utils.getEntry(allFiles, ["js", dir_root+"/"]) console.log(entry); module.exports = entry
同樣的,頁面入口文件也添加一個: $ touch config/webpack.plugins.js
var webpack = require("webpack") var path = require("path"); var utils = require("./utils.js") var ExtractTextPlugin = require("extract-text-webpack-plugin"); var HtmlWebpackPlugin = require("html-webpack-plugin"); var entry = require("./webpack.entry.js") var plugins = [ // 公共js提取 new webpack.optimize.CommonsChunkPlugin({ name: "vendors", // 將公共模塊提取,生成名為`vendors`的chunk minChunks: 3 // 提取至少3個模塊共有的部分 }), // 提取公共css樣式 new ExtractTextPlugin("./css/[name].css"), ] let dir_root = path.resolve(__dirname, "../src/view"); var pugFiles = utils.getAllFiles(dir_root, "pug") pugFiles = utils.getEntry(pugFiles, [".pug", dir_root+"/"]) for (var key in pugFiles) { if (pugFiles.hasOwnProperty(key)) { let opt = { filename: "./view/"+ key +".html", template: pugFiles[key], hash: true, minify: { //壓縮HTML文件 removeComments: true, //移除HTML中的注釋 collapseWhitespace: false //刪除空白符與換行符 } } if (entry.hasOwnProperty(key)) { opt["chunks"] = ["vendors", key] opt["inject"]= "body" } console.log(opt); plugins.push(new HtmlWebpackPlugin(opt)) } } module.exports = plugins
再次修改webpack的配置:
var entry = require("./config/webpack.entry.js") var plugins = require("./config/webpack.plugins.js") var webpackConfig = { entry, plugins, ... } module.exports = webpackConfig
可以看到,dist文件夾下,多了幾個html文件和js文件。
提取css到外部link,而非style標簽
這個解決辦法比較簡單,只需要用 extract-text-webpack-plugin 插件將css提取出來即可:
{ test: /.(scss|sass|css)$/, use: ExtractTextPlugin.extract({ fallback: "style-loader", use: [{ loader: "css-loader", options: { // // 0 => no loaders (default); 1 => postcss-loader; 2 => postcss-loader, sass-loader importLoaders: 2 } }, "postcss-loader", "sass-loader" ] }) }
再次打包的結果:
列出dis文件夾的目錄樹可以發現,多了一個css的文件夾。打開頁面可以發現,頁面中的style標簽已經被link替代了。
每次打包舊的文件依舊存在
每次執行webpack打包(當然在實際開發中應該使用熱更新服務器,不需要頻繁打包)都會產生一堆新的js文件。
解決辦法:
一是將打包的js文件的hash值去掉,這樣就會新的打包js文件,將舊的覆蓋。
二是使用 clean-webpack-plugin
var CleanWebpackPlugin = require("clean-webpack-plugin"); var plugins = [ // 每次打包前都清空dist文件 new CleanWebpackPlugin(["dist"], { root: path.resolve(__dirname, "../") }), // 公共js提取 new webpack.optimize.CommonsChunkPlugin({ name: "vendors", // 將公共模塊提取,生成名為`vendors`的chunk // minChunks: 3 // 提取至少3個模塊共有的部分 }), // 提取公共css樣式 new ExtractTextPlugin("./css/[name].css"), ]
批量新建文件
因為每個頁面基本都有3個文件:page.pug, page.js, page.scss,如果每次新加一個頁面都要手動新建3個文件的話,效率太低下,能用命令行解決的,當然要用命令行解決啦。
先寫個小腳本 newpage.sh:
#!/bin/sh if [[ $1 ]]; then filename=$1 touch ./src/js/$filename.js touch ./src/view/$filename.pug touch ./src/scss/$filename.scss fi
使用方式就是: $ ./newpage.sh filename,要運行該腳本,就需要先將腳本設置為可執行: $ sudo chmod +x ./newpage.sh。
還可以將它寫進 npm 的 package.json 的命令中,則命令可以變為:npm run new -- filename
{ "script": { "new": "./newpage.sh" } }
定義路徑常量
在編寫js時,因為有可能js文件是在很多級的目錄當中,如果每次都使用 .. 來定位上一層目錄的話,那么這個定位就會十分繁瑣。這時可以使用 webpack 提供的 resolve.alias 配置來使引入文件的時候變得更加方便簡單。
resolve: { alias: { scss: path.resolve(__dirname, "src/scss"), js: path.resolve(__dirname, "src/js"), view: path.resolve(__dirname, "src/view"), assets: path.resolve(__dirname, "src/assets") } }
這樣,在 other.js 中,就可以直接使用 require("scss/about.scss") 而不需要寫繁瑣的 require("../../scss/about.scss")。這樣就方便多了。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/84895.html
摘要:一組鏈式的將按照先后順序進行編譯。在最后一個,返回所預期的。運行在中,并且能夠執行任何可能的操作。用于對傳遞配置。分開的每個部分都相對于當前目錄解析。 webpack自稱能夠打包任何文件,這句話咋聽一下好像在吹牛逼,因為webpack本身只能理解JavaScript。但是由于webpack中有loader的存在,可以將所有類型的文件轉換為webpack能夠處理的有效模塊,然后利用we...
摘要:然而,這些模板并不限制你自己對于使用的架構組織和選擇類庫。目前可用的模板包括全功能的,包括熱加載,靜態檢測,單元測試一個簡易的,以便于快速開始。 最近, 尤大在和人對噴的時候,悄然放出了一個大招,于是為了追趕他的步伐,趕緊試驗了下,并且把原文給大家翻譯下。 原文地址:Announcing vue-cli 譯文源地址: Vuejs自己的構建工具 先上原文翻譯: 最近有很多大量關于Reac...
摘要:五六月份推薦集合查看最新的請點擊集前端最近很火的框架資源定時更新,歡迎一下。蘇幕遮燎沈香宋周邦彥燎沈香,消溽暑。鳥雀呼晴,侵曉窺檐語。葉上初陽乾宿雨,水面清圓,一一風荷舉。家住吳門,久作長安旅。五月漁郎相憶否。小楫輕舟,夢入芙蓉浦。 五、六月份推薦集合 查看github最新的Vue weekly;請::點擊::集web前端最近很火的vue2框架資源;定時更新,歡迎 Star 一下。 蘇...
摘要:五六月份推薦集合查看最新的請點擊集前端最近很火的框架資源定時更新,歡迎一下。蘇幕遮燎沈香宋周邦彥燎沈香,消溽暑。鳥雀呼晴,侵曉窺檐語。葉上初陽乾宿雨,水面清圓,一一風荷舉。家住吳門,久作長安旅。五月漁郎相憶否。小楫輕舟,夢入芙蓉浦。 五、六月份推薦集合 查看github最新的Vue weekly;請::點擊::集web前端最近很火的vue2框架資源;定時更新,歡迎 Star 一下。 蘇...
閱讀 2105·2021-11-23 10:06
閱讀 3456·2021-11-11 16:54
閱讀 3337·2019-08-29 17:31
閱讀 3563·2019-08-29 17:05
閱讀 2166·2019-08-26 13:36
閱讀 2155·2019-08-26 12:17
閱讀 520·2019-08-26 12:12
閱讀 1668·2019-08-26 10:19