成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

使用webpack從0搭建多入口網(wǎng)站腳手架,可復(fù)用導(dǎo)航欄/底部通欄/側(cè)邊欄,根據(jù)頁(yè)面文件自動(dòng)更改配置

jaysun / 1914人閱讀

摘要:官方推薦不寫重復(fù)的配置,即把本地和生產(chǎn)環(huán)境共用的配置放到一個(gè)文件,然后通過進(jìn)行合并我們可以看到,通過插件,將共用配置和開發(fā)的配置進(jìn)行合并定義了全局變量這個(gè)插件是為了在我們?cè)试S后,自動(dòng)打開頁(yè)面,避免每次都手動(dòng)打開。

之前只知道webpack很強(qiáng)大,但是一直沒有深入學(xué)習(xí)過,這次從頭看了一下教程,然后從0開始搭建了一個(gè)多入口網(wǎng)站的開發(fā)腳手架,期間遇到過很多問題,所以有心整理一下,希望能給大家一點(diǎn)幫助。

多HTML網(wǎng)站使用webpack的必要性

假如我們接到這樣一個(gè)任務(wù),開發(fā)一個(gè)簡(jiǎn)單的官網(wǎng),比如只有十幾個(gè)html頁(yè)面。項(xiàng)目很簡(jiǎn)單,我們沒有必要使用什么大型框架,但是如果只是傳統(tǒng)的寫幾個(gè)html、js和css,肯定會(huì)遇到這幾個(gè)問題:

網(wǎng)站導(dǎo)航和底部通欄是每個(gè)頁(yè)面都共有的,如何實(shí)現(xiàn)復(fù)用?如果不復(fù)用,那么有改動(dòng)的時(shí)候就要改n個(gè)頁(yè)面,未免太傻

如何在更改后強(qiáng)制清空用戶緩存?我們不可能要求用戶手動(dòng)去清除瀏覽器緩存,那樣太傻

我想使用ES6進(jìn)行js的開發(fā),如何解決瀏覽器兼容性問題?

我想使用less進(jìn)行css樣式開發(fā),如何轉(zhuǎn)換?

可以看出,沒有自動(dòng)化打包工具的加入,這些問題我們是很難解決的,因此使用webpack勢(shì)在必行。

要實(shí)現(xiàn)的目標(biāo)

看到這里,可能有的同學(xué)就急了,別廢話,感覺進(jìn)入正題吧,不!我們先定目標(biāo)!無(wú)論做什么事情,都要先定目標(biāo),而不是干到哪里算哪里,這樣是不會(huì)有大的提升的,正是在邁向目標(biāo)的路上克服各種問題,我們才有進(jìn)步,在進(jìn)行這個(gè)腳手架搭建之前,我希望它是這樣的

能夠打包成多個(gè)html文件和js文件,即支持多入口

文件名稱都要帶上hash值,解決緩存問題

能夠復(fù)用網(wǎng)站的頭部導(dǎo)航欄和底部通欄

通過采用less進(jìn)行樣式的編寫

能夠支持ES6開發(fā)

用起來(lái)要方便,增加頁(yè)面不需要手動(dòng)去更改webpack的入口設(shè)置,希望能夠根據(jù)目錄下的文件自動(dòng)配置

不希望通過js動(dòng)態(tài)插入css樣式,這樣會(huì)造成頁(yè)面閃爍,希望html中直接引入css地址,就像平時(shí)開發(fā)那樣

能夠?qū)崟r(shí)看到開發(fā)的效果

build能夠?qū)Υa進(jìn)行壓縮

好了,目標(biāo)定了,開工

目錄結(jié)構(gòu)

別急,我們先來(lái)捋一捋目錄,別著急寫代碼,一個(gè)好的目錄,能讓我們思路清晰,我的目錄結(jié)構(gòu)如下

+ config                    //環(huán)境變量配置文件,開發(fā)模式和生產(chǎn)模式使用不同的環(huán)境變量,比如接口地址,開發(fā)環(huán)境用的接口域名是http://a.com,生產(chǎn)環(huán)境使用的是http://b.com
    - dev.env.js            //本地開發(fā)變量   
    - prod.env.js           //生產(chǎn)環(huán)境變量
+ src                       
    + css                   //自己的less組件或者第三方css庫(kù)
         + component        //自己組件的less
         + lib              //第三方的css庫(kù),比如bootstrap
    + html                  //html代碼,主要是一些模板,如頭部導(dǎo)航,底部通欄,側(cè)邊欄
         + tpl              //模板文件
    + img                   //圖片文件
    + js                    //自己的js組件庫(kù)或者第三方j(luò)s庫(kù)
         + mod              //自己的js組件放這里
         + lib              //第三方j(luò)s庫(kù)
    + page                  //頁(yè)面文件
         + index            //這個(gè)根據(jù)自己情況設(shè)置,有的頁(yè)面相關(guān)性強(qiáng),可以放到一個(gè)文件夾下,比如一個(gè)user文件夾,可以放個(gè)人中心的所有頁(yè)面
             - index.html   //每個(gè)頁(yè)面都要有一個(gè)html
             - index.js     //每個(gè)頁(yè)面都要有一個(gè)js,名稱和html的名稱保持一致
             - index.less   //每個(gè)頁(yè)面都要有一個(gè)同名less文件
          + test
             - test.html
             - test.js
             - test.less    
             
+ webpack                   //webpack的配置文件
     - dev-server.js        //開發(fā)服務(wù)設(shè)置,可以通過localhost訪問頁(yè)面,頁(yè)面的實(shí)時(shí)編譯
     - webpack.common.js    //開發(fā)環(huán)境和生產(chǎn)環(huán)境通用配置
     - webpack.dev.js       //開發(fā)環(huán)境特有的配置
     - webpack.prod.js      //生產(chǎn)環(huán)境特有的配置

首先是config目錄,目前我主要放一些環(huán)境變量,就是開發(fā)環(huán)境和生產(chǎn)環(huán)境所不同的變量,比如接口地址,我們開發(fā)的時(shí)候,用本地的api接口地址,而打包的時(shí)候,要換成生產(chǎn)環(huán)境api地址。

webpack目錄存放webpack的配置文件,其中開發(fā)和生產(chǎn)通用配置 放到webpack.common.js中,開發(fā)特有配置放到webpack.dev.js中,生產(chǎn)特有配置放到webpack.prod.js中。

src是我們開發(fā)的主目錄,其中page目錄放置我們的頁(yè)面文件,這里可能和平時(shí)有所不同,我把每個(gè)頁(yè)面用到的html、js和less文件放到了一起,有的同學(xué)可能把所有html放到一個(gè)目錄下,js放到一個(gè)目錄下,但是這樣存在一個(gè)問題,每次改動(dòng)頁(yè)面,都要去翻目錄,非常的不方便,我們應(yīng)該把這種高度相關(guān)的文件放到一起,而提取的各種css組件或js組件可以和頁(yè)面分開放置。

github地址:https://github.com/501351981/...

多入口配置

webpack支持多入口,即給定多個(gè)入口js文件,可以輸出多個(gè)js文件,那么html怎么辦呢?我希望開發(fā)過程是這樣的,我在html中設(shè)置標(biāo)題、SEO等信息,編寫HTML內(nèi)容代碼,webpack把相關(guān)的js文件自動(dòng)插入到html底部就行,可以的,這需要用到html-webpack-plugin 插件,可以通過調(diào)用html模板文件打包最終html。

安裝html-webpack-plugin

npm install --save-dev html-webpack-plugin

webpack.common.js中多入口配置

const HtmlWebpackPlugin = require("html-webpack-plugin");

module.exports={

    entry:[
        index:"../src/page/index/index.js",
        test:"../src/page/test/test.js"
    ],
    
    output: {
        filename: "[name].[hash].js",   //輸出名稱后面跟哈希值,解決緩存問題
        path: path.resolve(__dirname,"../dist")
    },

    ....
    
    plugins: [
      new HtmlWebpackPlugin({
         filename: "index.html",
         template: "../src/page/index/index.html",
         chunks: ["index"],
      })
      
      new HtmlWebpackPlugin({
         filename: "test.html",
         template: "../src/page/test/test.html",
         chunks: ["test"],
      })
    ]
}

這樣設(shè)置存在一個(gè)問題,每次新增一個(gè)頁(yè)面,我就要到這里添加一下,未免很麻煩,我們其實(shí)可以通過讀取 src/page下的js文件,自動(dòng)加入入口配置;讀取 src/page下的所有html文件,自動(dòng)調(diào)用new HtmlWebpackPlugin進(jìn)行實(shí)例化。

讀取目錄下所有文件名,我們需要引入glob,先安裝

npm install --save-dev glob

改進(jìn)后的配置

const glob = require("glob")
const CleanWebpackPlugin = require("clean-webpack-plugin");

//多入口js的配置,讀取src/page下所有的js文件
function entries() {
    let jsDir = path.resolve(__dirname, "../src/page")
    let entryFiles = glob.sync(jsDir + "/**/*.js")
    let map = {};

    for (let i = 0; i < entryFiles.length; i++) {
        let filePath = entryFiles[i];
        let filename = filePath.substring(filePath.lastIndexOf("/") + 1, filePath.lastIndexOf("."));
        map[filename] = filePath;
    }
    return map;
}

//讀取多個(gè)html模板,進(jìn)行插件實(shí)例化
function newHtmlWebpackPlugins(){
    let jsDir = path.resolve(__dirname, "../src/page")
    let htmls = glob.sync(jsDir + "/**/*.html")
    let plugins=[]

    for (let i = 0; i < htmls.length; i++) {
        let filePath = htmls[i];
        let filename_no_extension = filePath.substring(filePath.lastIndexOf("/") + 1, filePath.lastIndexOf("."));
        let filename=filename_no_extension.concat(".html")
       plugins.push(new HtmlWebpackPlugin({
           filename: filename,
           template: filePath,
           chunks: [filename_no_extension],
       }))
    }

    return plugins
}


module.exports={

    entry:entries(),
    
    output: {
        filename: "[name].[hash].js",
        path: path.resolve(__dirname,"../dist")
    },

    ....
    
    plugins: [
      ...newHtmlWebpackPlugins()
    ]
}

好了,現(xiàn)在新增頁(yè)面不需要更改webpack配置了,只需要重新運(yùn)行一下 npm run start即可

共有頭部和底部的復(fù)用

頭部導(dǎo)航和底部通欄我們各個(gè)頁(yè)面都是一樣的,因此需要引入,那么html中怎么引入另一個(gè)html呢,這需要用到raw-loader 或 html-withimg-loader

安裝raw-loader,raw-loader可以加載文件原始內(nèi)容(utf-8格式)

npm install --save-dev raw-loader
//目錄結(jié)構(gòu)

+ src                       
   
    + html                  
         + tpl              
             - navbar.html  //共用的頭部導(dǎo)航  
             - footer.html  //共用的底部導(dǎo)航
    + page                  //頁(yè)面文件
         + index            
             - index.html   
        
          + test
             - test.html

我們?cè)趇ndex.html中可以這么引用導(dǎo)航和底部通欄


<%=require("raw-loader!../../html/tpl/navbar.html")%>


首頁(yè)的內(nèi)容在這里

<%=require("raw-loader!../../html/tpl/footer.html")%>

最初我在查找解決方案的時(shí)候,看到文章推薦使用raw-loader,但是發(fā)現(xiàn)這樣存在一個(gè)問題,就是導(dǎo)航中無(wú)法引用本地的圖片,比如導(dǎo)航中引用一個(gè)logo圖片,是找不到的,因?yàn)槲覀兇虬臅r(shí)候也會(huì)對(duì)圖片進(jìn)行處理,后面添加hash值,直接寫圖片路徑是不行的,后來(lái)我改用 html-withimg-loader解決了

安裝html-withimg-loader,顧名思義,這個(gè)插件可以加載帶有圖片的html

npm install --save-dev html-withimg-loader

<%=require("html-withimg-loader!../../html/tpl/navbar.html")%>


首頁(yè)的內(nèi)容在這里

<%=require("html-withimg-loader!../../html/tpl/footer.html")%>

順便提一句,html中引用圖片地址是需要這樣寫的,需要通過require才行,簡(jiǎn)單的填寫圖片地址是不行的

支持ES6編寫js

相信大家現(xiàn)在都已經(jīng)學(xué)過ES6了,可是鑒于瀏覽器的兼容性,還沒法隨心所欲的用,需要插件支持,我們首先安裝

npm install --save-dev babel-loader babel-core babel-preset-env

添加webpack配置

webpack.common.js,我們只對(duì)src目錄下的js進(jìn)行轉(zhuǎn)換

{
    test: /.js$/,
    use: {
        loader: "babel-loader"
    },
    include: path.resolve(__dirname,"../src")
},

同時(shí)在項(xiàng)目目錄下添加一個(gè)名為.babelrc的文件,對(duì)babel進(jìn)行設(shè)置,支持占有率大于1%的瀏覽器的最近2個(gè)版本

{
  "presets": [
    ["env",{
      "targets": {
        "browsers": ["> 1%", "last 2 versions"]
      }
    }]
  ],
}

babel只是將ES6語(yǔ)法轉(zhuǎn)為ES5的語(yǔ)法,比如箭頭函數(shù)轉(zhuǎn)為function(){},但是對(duì)一些ES6特有的功能沒有轉(zhuǎn)換,比如new Map(),打包之后還是new Map(),我們還需要再安裝一個(gè)插件,完成這個(gè)轉(zhuǎn)換工作。

npm install --save-dev babel-plugin-transform-runtime

更改.babelrc文件

{
  "presets": [
    ["env",{
      "targets": {
        "browsers": ["> 1%", "last 2 versions"]
      }
    }]
  ],
  "plugins": ["transform-runtime"]    //引入插件
}

現(xiàn)在可以放心大膽的使用ES6了

使用Less編寫樣式

首先還是安裝相關(guān)插件

npm install --save-dev less less-loader css-loader style-loader

webpack.common.js配置

{
    test: /.css$/,
    use:["style-loader","css-loader","less-loader"]
},

在index.js文件中,我們就可以這樣引入less文件了

import "./index.less"

打包之后,運(yùn)行html頁(yè)面,index.js會(huì)動(dòng)態(tài)把css樣式插入到html頁(yè)面,這樣會(huì)造成一個(gè)問題,剛加載html的時(shí)候是一個(gè)樣式,js插入css樣式后是另一個(gè)樣式,造成頁(yè)面閃爍一下,體驗(yàn)不好(技術(shù)也要追求用戶體驗(yàn)啊,不光是產(chǎn)品經(jīng)理的事)。這有兩個(gè)解決方案吧,第一個(gè)就是在JS未加載完成之前,顯示一個(gè)loading動(dòng)畫,把整個(gè)頁(yè)面遮蓋住,第二個(gè)就是把css文件路徑打包進(jìn)html中,不要通過js動(dòng)態(tài)添加,我選用的第二個(gè)方案。

我們要把less文件打包到一個(gè)css文件中,需要用到插件extract-text-webpack-plugin

npm install --save-dev extract-text-webpack-plugin

webpack.common.js

const ExtractTextPlugin = require("extract-text-webpack-plugin");

module.exports={
    rules: [
        {
            test: /.less$/,
            use: ExtractTextPlugin.extract({
                fallback: "style-loader",
                use: "css-loader!less-loader"
            })

       },
    ]
}

plugins: [
   new ExtractTextPlugin("[name].[hash:8].css"),
]

這樣打包之后的html中會(huì)引入css文件,類似這樣

    
webpack配置

實(shí)際在我從0開始搭建的過程中,是先進(jìn)行webpack這塊的配置的,之所以放到最后是不想影響主干內(nèi)容,下面我們也簡(jiǎn)單介紹一下我的webpack配置。

webpack官方推薦不寫重復(fù)的配置,即把本地和生產(chǎn)環(huán)境共用的配置放到一個(gè)文件,然后通過merge進(jìn)行合并

webpack.dev.js

const webpack = require("webpack");
const merge = require("webpack-merge");
const common = require("./webpack.common");

var OpenBrowserPlugin = require("open-browser-webpack-plugin");

const env=require("../config/dev.env")

module.exports=merge(common,{
    mode:"development",
    devtool: "inline-source-map",
    plugins:[
        new webpack.DefinePlugin({
            "process.env": env
        }),
        new webpack.NamedModulesPlugin(),
        new webpack.HotModuleReplacementPlugin(),
        new OpenBrowserPlugin({ url: "http://localhost:5000" })
    ],
})

我們可以看到,通過webpack-merge插件,將共用配置webpack.common.js和開發(fā)的配置進(jìn)行合并

new webpack.DefinePlugin({
            "process.env": env
 }),

DefinePlugin定義了全局變量process.env

new OpenBrowserPlugin({ url: "http://localhost:5000" })

這個(gè)插件是為了在我們?cè)试Snpm run start后,自動(dòng)打開頁(yè)面http://localhost:5000,避免每次都手動(dòng)打開。
webpack-dev-server 為我們提供了一個(gè)簡(jiǎn)單的 web 服務(wù)器,并且能夠?qū)崟r(shí)重新加載,讓我們可以實(shí)時(shí)看到開發(fā)結(jié)果,關(guān)于web服務(wù)器的配置,我放到了dev-server.js中

const webpackDevServer = require("webpack-dev-server");
const webpack = require("webpack");

const config = require("./webpack.dev");
const options = {
    contentBase: "./dist",
    hot: true,
    host: "localhost",
};

webpackDevServer.addDevServerEntrypoints(config, options);
const compiler = webpack(config);
const server = new webpackDevServer(compiler, options);

server.listen(5000, "localhost", () => {
    console.log("dev server listening on port 5000");
});

在package.json中,我們添加兩個(gè)腳本

"scripts": {
  "start": "node webpack/dev-server.js",
  "build": "npx webpack --config webpack/webpack.prod.js",
},

這樣我們就可以在命令行輸入兩個(gè)命令

npm run start :進(jìn)入開發(fā)模式

npm run build:打包生產(chǎn)環(huán)境代碼

好了,基本上把我做的這個(gè)腳手架介紹完了,實(shí)際要理解還需要自己去試,看是一回事,做出來(lái)又是另一回事,給別人講明白那就更不容易了,前端路漫漫,大家努力吧。

github地址:https://github.com/501351981/...

這個(gè)腳手架還不完善,不過基本夠用了,后面我還會(huì)再做幾個(gè)腳手架,比如結(jié)合vue進(jìn)行多頁(yè)面開發(fā)或移動(dòng)端H5開發(fā),有興趣可以持續(xù)關(guān)注。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/108735.html

相關(guān)文章

  • 使用webpack0搭建入口網(wǎng)站手架復(fù)用導(dǎo)航/底部/側(cè)邊,根據(jù)頁(yè)面文件自動(dòng)更改配置

    摘要:官方推薦不寫重復(fù)的配置,即把本地和生產(chǎn)環(huán)境共用的配置放到一個(gè)文件,然后通過進(jìn)行合并我們可以看到,通過插件,將共用配置和開發(fā)的配置進(jìn)行合并定義了全局變量這個(gè)插件是為了在我們?cè)试S后,自動(dòng)打開頁(yè)面,避免每次都手動(dòng)打開。 之前只知道webpack很強(qiáng)大,但是一直沒有深入學(xué)習(xí)過,這次從頭看了一下教程,然后從0開始搭建了一個(gè)多入口網(wǎng)站的開發(fā)腳手架,期間遇到過很多問題,所以有心整理一下,希望能給大家...

    isLishude 評(píng)論0 收藏0
  • 基于webpack4.x, babel7.x 搭建頁(yè)面手架, 簡(jiǎn)化前端開發(fā)環(huán)境配置,開箱即用,

    摘要:開箱即用的多頁(yè)面腳手架基于模塊化開發(fā)可復(fù)用的現(xiàn)代化網(wǎng)站感興趣的朋友,請(qǐng)點(diǎn)個(gè)及時(shí)關(guān)注項(xiàng)目更新請(qǐng)點(diǎn)個(gè)項(xiàng)目請(qǐng)?zhí)崽匦灾С智昂蠖朔蛛x開發(fā)配置完整的打包方案支持本地開發(fā)熱更新集成代碼風(fēng)格校驗(yàn)支持編寫源碼,編譯生成生產(chǎn)代碼內(nèi)置開發(fā)環(huán)境,自動(dòng)加樣式前綴自 Webpack-seed 開箱即用的多頁(yè)面腳手架, 基于webpack4.2x babel7.1x模塊化開發(fā)可復(fù)用的現(xiàn)代化網(wǎng)站(Without Vu...

    junfeng777 評(píng)論0 收藏0
  • flutter實(shí)戰(zhàn)1:完成一個(gè)有側(cè)邊的主界面

    摘要:側(cè)邊欄我們先圖解一下側(cè)邊欄的結(jié)構(gòu)整個(gè)側(cè)邊欄主從上到下按區(qū)塊分別放置了賬號(hào)和若干功能項(xiàng)分割線的列表,很容易想到使用布局控件。賬號(hào)信息區(qū)域中有賬號(hào)頭像粉絲頭像賬號(hào)文字信息和背景圖,這塊我們可以使用控件庫(kù)的控件實(shí)現(xiàn)。 經(jīng)過2周的學(xué)習(xí),看過筆記1-8的小伙伴們已經(jīng)有不少開始自己寫APP了,我也按耐不住這股熱情,想要自己開發(fā)個(gè)APP玩玩,so,從本篇起,仿造一個(gè)APP,項(xiàng)目從0開始,每篇增加一些...

    孫淑建 評(píng)論0 收藏0
  • 超詳細(xì)動(dòng)手搭建一個(gè)Vuepress站點(diǎn)及開啟PWA與自動(dòng)部署

    摘要:五一之前就想寫一篇關(guān)于的文章結(jié)果朋友結(jié)婚就不了了之了。記得最后一定要看注意事項(xiàng)更新倉(cāng)庫(kù)介紹官網(wǎng)類似一個(gè)極簡(jiǎn)的靜態(tài)網(wǎng)站生成器用來(lái)寫技術(shù)文檔不能在爽。當(dāng)然搭建成博客也不成問題。構(gòu)建與自動(dòng)部署用的或者的都可以也可以搭建在自己的服務(wù)器上。 五一之前就想寫一篇關(guān)于Vuepress的文章,結(jié)果朋友結(jié)婚就不了了之了。記得最后一定要看注意事項(xiàng)! 更新:coding倉(cāng)庫(kù):https://git.dev...

    zhoutk 評(píng)論0 收藏0
  • 今天開始,拿起VuePress打造屬于自己的專屬博客

    摘要:故九萬(wàn)里,則風(fēng)斯在下矣,而后乃今培風(fēng)背負(fù)青天,而莫之夭閼者,而后乃今將圖南。這里是文件的內(nèi)容部分最后更新時(shí)間最后更新時(shí)間默認(rèn)不開啟,它是基于提交的時(shí)間戳,所以我們的靜態(tài)站點(diǎn)是需要通過的倉(cāng)庫(kù)進(jìn)行管理的,并且它是按的時(shí)間來(lái)計(jì)算的。VuePress(0.x版本) 本blog配套了一個(gè)基于 VuePress 的一個(gè)簡(jiǎn)單的配置案例,此配置案例包含了本blog絕大部分配置案例,更多詳情請(qǐng)移步這里VueP...

    dantezhao 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<