webpack搭建vue開發環境

首先全局安裝:node、npm、webpack、webpack-clicss

npm install webpack webpack-cli -D

接着建立打包配置文件:webpack.config.jshtml

打包圖片

npm init -y //生成配置文件package.json

此時webpack-test目錄以下:
image.png前端

npm install url-loader -S  
//安裝file-loader
//安裝url-loader到當前並記錄到package.json
npm install file-loader -S 
 //安裝file-loader :
 //生成的文件的文件名就是文件內容的
 //MD5哈希值並會保留所引用資源的原始擴展名

在開發模式的狀況下:mode:'development'時:不管你的圖片是否 使用,在(limit設置數值要在被打包的圖片的大小範圍之內的)都會生成dataUrl打包到bundele.js,而limit設置的數值小於圖片自己大小,也會直接打包到dist文件當中,但只會生成圖片自己而不是dataUrl
在生產模式的狀況下:mode:'production'時:在(limit設置數值要在被打包的圖片的大小範圍之內的),圖片使用:會生成dataUrl打包到bundle.js裏面。不使用不會打包成dataUrl,也不會生成圖片自己打包到dist文件中(直接去除無用代碼)。若是設置的limit小於被打包圖片的大小,不管使用使用了圖片都會生成圖片自己在dist文件當中。總結:優先級看來都是limit比較高vue

轉換JS語句(非es5轉換)

npm install babel-loader@8.0.0-beta.0 @babel/core @babel/preset-env webpack
// 把es6那些轉換成es5
npm install @babel/plugin-transform-runtime -D 
npm install @babel/runtime -D
// 對es6降級es5的一個墊片,能夠按需引入,模塊化加載,不污染全局

此時目錄以下:
image.pngnode

  • babel-loader @babel/core 能夠支持es6語法
  • @babel/preset-env 是根據瀏覽器或者運行環境來將es6轉化成es5,好比根據browserslist
  • 補充說明1:@babel/polyfill 是對es6降級es5的一個墊片,是對babel-loader的補充,可是會污染全局,不能按需引入,不建議這種方式
  • 補充說明2:@babel/runtime @babel/plugin-transform-runtime也是對es6降級es5的一個墊片,能夠按需引入,模塊化加載,不污染全局,推薦使用
  • file-loader 或者 url-loader能夠支持引入文件
  • file-loader不支持小文件轉化爲base64格式,可是能夠爲文件名添加hash值,url-loader能夠支持小文件轉化爲base64格式,這兩個能夠搭配使用

詳情可點擊於此:https://babeljs.io/docs/en/next/babel-plugin-transform-runtime.htmlwebpack

打包CSS樣式

處理sass
npm install sass-loader node-sass -D 
// 安裝sass-loader、node-sass
npm install style-loader css-loader -D 
//安裝 style-loader、css-loader

在webpack.config.js得module得rules:中添加
image.png
css-loader詳情:https://www.webpackjs.com/loaders/css-loader/
sass-loader詳情:https://www.webpackjs.com/loaders/sass-loader/
而後新建文件夾css裏面建立test.scss文件測試一下:
此時目錄以下:
image.png
而後此時輸入webpack進行打包,但出現了一次錯誤,不管如何檢查,感受都好像沒啥問題。
image.png
表示我文件錯誤出如今scss上,可是反覆研究發現仍是沒問題呀?
最後發現是安裝sass-loader版本有問題,這裏須要打開你得在package.json文件,修改sass-loader得版本,修改成7.0.0就能夠了
image.png
緊接着從新輸入 npm i從新安裝依賴,ok打包成功!
image.pnggit

處理less
npm install less-loader less -D
 //安裝less

而後webpack.config.js添加規則:
image.png
less-loader詳情:https://www.webpackjs.com/loaders/less-loader/
而後在css文件夾中建立測試文件test2.less
image.png
而後進行打包測試,完成!!!!es6

我想着要是把打包的css和js分開怎麼辦?

這時候咱們須要加入一個插件:MiniCssExtractPlugingithub

npm install mini-css-extract-plugin -D
//安裝MiniCssExtractPlugin

提示:另一個插件ExtractTextWebpackPlugin也能夠進行分離,但在Webpack官方顯示webpack4的ExtractTextWebpackPlugin不能用於css,須要改用MiniCssExtractPlugin
安裝完後webpack.config.js文件頭部直接引入:web

const MiniCssExtractPlugin = require('mini-css-extract-plugin');

其次還須要添加到rules和plugins,並進行修改:
image.png

要處理css兼容各個瀏覽器,自動在css添加前綴,須要下載如下插件

npm install postcss-loader autoprefixer postcss -D
//在以前項目webpack1.x版本升級到webpack4.x版本,使用postcss-loader代替autoprefixer。這邊同時作一下兼容。

安裝完後須要先在webpack.config.js同目錄下新建文件postcss.config.js,注意這個文件不建立是編譯不成功的,編輯內容爲:

module.exports = {
    plugins: [
        require('autoprefixer')({
            /* ...options */ })
    ]
}
//postcss.config.js

接着在webpack.config.js文件中添加:
image.png
須要注意的是:使用postcss-loader時,須要在css-loader以後style-loader,但要其餘預處理程序加載程序(例如sass|less|stylus-loader,若是使用)以前**使用它。

打包字體

新建font文件夾存放字體包,並在css中引入,其次還須要在webpack.config.js中加入loader內容(代碼以下:)

{
    test: /\.(woff|woff2|eot|ttf|otf)$/,
    use: [
        'file-loader'
    ]
}

image.png

NPM 腳本

考慮到用 CLI 這種方式來運行本地的 webpack 不是特別方便,咱們能夠設置一個快捷方式。在 package.json 添加一個 npm 腳本(npm script):
image.png
(這一段是官方的原話,這邊引用一下,就當是我我的學習筆記吧)
而後運行如下命令看看是否正常:

npm run build  //打包

自動引入打包生成得js得插件:html-webpack-plugin

npm install html-webpack-plugin -D
 //安裝HtmlWebpackPlugin

緊接着進行配置,代碼以下:

const HtmlWebpackPlugin = require('html-webpack-plugin'); //自動引入打包生成得js

 plugins: [ //plugins 插件用於執行範圍包括,從打包優化和壓縮,一直到從新定義環境中的變量
        new HtmlWebpackPlugin({
            minify: {
                collapseWhitespace: true, //清除空格
                removeAttributeQuotes: true, //清除多餘引號
                removeComments: true //刪除註釋

            },
            title: 'Output Management', //替代原title,須要在src文件夾下的index.html中配置
            template: path.resolve(__dirname, './src/index.html'), //要打包的html文件路徑
            filename: 'index.html' //打包後輸出的html文件名
        })
    ],

而後在src文件夾下新建文件index.html,由於上面使用了自定了title,因此須要在index.html中設置title:

<title><%= htmlWebpackPlugin.options.title %></title>

//把 Document 設置爲 <%= htmlWebpackPlugin.options.title %>

image.png

輸入npm run build,此時將生成了打包後dist文件夾,裏面的index.html的title已經被替換,並自動引入了js和css文件:
image.png
html-webpack-plugin詳情:https://webpack.js.org/guides/output-management/#conclusion

清理/dist文件夾:

npm install clean-webpack-plugin -D
//安裝clean-webpack-plugin

安裝後引入配置:

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

plugins: [  //plugins 插件用於執行範圍包括,從打包優化和壓縮,一直到從新定義環境中的變量
        new CleanWebpackPlugin() 
]

clean-webpack-plugin詳情:https://webpack.js.org/guides/output-management/#conclusion

壓縮單獨的css文件

npm install  optimize-css-assets-webpack-plugin -D
//安裝optimize-css-assets-webpack-plugin

配置文件:

const OptimizeCssAssetsWebpackPlugin = require('optimize-css-assets-webpack-plugin'); //壓縮單獨的css文件

plugins: [ //plugins 插件用於執行範圍包括,從打包優化和壓縮,一直到從新定義環境中的變量
        new OptimizeCssAssetsWebpackPlugin(),
]

optimize-css-assets-webpack-plugin詳情:https://www.npmjs.com/package/optimize-css-assets-webpack-plugin

去除無用的css樣式

npm install purifycss-webpack purify-css -D
//安裝purifycss-webpack purify-css
const PurifyCSSPlugin = require('purifycss-webpack'); //css優化去重複無效代碼
const glob = require('glob'); //css優化
plugins: [ //plugins 插件用於執行範圍包括,從打包優化和壓縮,一直到從新定義環境中的變量
        new PurifyCSSPlugin({
            paths: glob.sync(path.join(__dirname, './src/*.html')),
        })
]

purifycss-webpack-plugin詳情:https://www.npmjs.com/package/purifycss-webpack

使用DefinePlugin設定建立全局變量

所以利用全局變量這一點來設置全局變量來區分開發環境和正式環境。
webpack.config.js 文件代碼以下:

const webpack = require('webpack');

new webpack.DefinePlugin({
'SERVICE_URL': JSON.stringify('https://dev.example.com'),
  PROCESS.VERSION:  JSON.stringify('2.0.1'),
  PROCESS.ENVIRONMENT:  '"dev"'
  'process.env': {
        NODE_ENV: JSON.stringify(process.env.NODE_ENV)
    }               
});

注意:該plugin直接作文本替換,指定的值必須包括引號。
通常來說,須要使用單引號"production"或使用JSON.stringify('production')
DefinePlugin中的每一個鍵,是一個標識符或者經過.做爲多個標識符。

  • 若是value是一個字符串,它將會被當作code片斷
  • 若是value不是字符串,它將會被stringify(包括函數)
  • 若是value是一個對象,則全部key的定義方式相同。
  • 若是key有typeof前綴,它只是對typeof 調用定義的。

process.env.NODE_ENV :大概說說這個變量的問題,在node中,有全局變量process表示的是當前的node進程。process.env 屬性返回的是一個包含用戶環境信息的對象,process.env中並不存在NODE_ENV這個東西。NODE_ENV是用戶一個自定義的變量,在webpack中它的用途是判斷生產環境或開發環境的依據的。
咱們能夠直接在cmd環境配置便可,查看環境變量,添加環境變量,刪除環境變量等操做。

#node中經常使用的到的環境變量是NODE\_ENV,首先查看是否存在 
set NODE\_ENV 

#若是不存在則添加環境變量 
set NODE\_ENV\=production 

#環境變量追加值 set 變量名\=%變量名%;變量內容 
set path\=%path%;C:\\web;C:\\Tools 

#某些時候須要刪除環境變量 
set NODE\_ENV\=

所以利用這一點,咱們能夠在咱們package.json文件中進行修改,
package.json 文件代碼以下:

"scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "build": "NODE_ENV=production webpack",
    "dev": "NODE_ENV=development"
  },

當咱們設置完之後 npm run build 打包,這個時候process.env.NODE_ENV 纔會真正打印出 production,
能夠嘗試在src文件下的index.js進行打印測試

console.log(process.env.NODE_ENV)
//注意這裏的打印的process.env.NODE_ENV 是我在webpack.config.js經過process.env.NODE_ENV利用new webpack.DefinePlugin()插件設置的屬性值,

這時可能會出現一個打包異常:
image.png
這是咱們能夠利用這個腳本:

cross-env跨平臺設置和使用環境變量的腳本

當咱們使用 NODE_ENV = production 來設置環境變量的時候,大多數windows命令會提示將會阻塞或者異常,或者,windows不支持NODE_ENV=development的這樣的設置方式,會報錯。所以咱們就可使用 cross-env命令。
先安裝:

npm install cross-env -D

而後在package.json中進行修改:

"scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "build": "cross-env NODE_ENV=production webpack",
    "dev": "cross-env NODE_ENV=development"
  },

最後從新打包編譯:
image.png
成功!!!

接下里也順便設置全局變量來區分開發環境和正式環境:


根目錄下建立config文件夾並新建api.js:

const NODE_ENV = process.env.NODE_ENV;

const config = {
     production: {
        FOO_API: 'production.foo.com',
        BAR_API: 'production.bar.com',
        BAZ_API: 'production.baz.com',
     },
     development: {
        FOO_API: 'development.foo.com',
        BAR_API: 'development.bar.com',
        BAZ_API: 'development.baz.com',
     },
     test: {
        FOO_API: 'test.foo.com',
        BAR_API: 'test.bar.com',
        BAZ_API: 'test.baz.com',
     }
}

module.exports = config[NODE_ENV];

而且package.json的scripts設置爲

"scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "build:qa": "cross-env NODE_ENV=test webpack",
    "build:dev": "cross-env NODE_ENV=development",
    "build:prod": "cross-env NODE_ENV=production webpack"
  },

webpack.config.js:

const apiConfig = require('./config/api'); //引入config/api.js 文件
new webpack.DefinePlugin({
    'SERVICE_URL': JSON.stringify('https://dev.example.com'),
    'process.env': {
        NODE_ENV: JSON.stringify(process.env.NODE_ENV)
    },
    API_CONFIG: JSON.stringify(apiConfig)
}),

這時候npm run build 在index.js輸出打印一下

console.log(API_CONFIG.BAR_API);
//執行結果:production.bar.com

source-map 方便調試代碼

devtool可選值:

  • source-map 【用於生產環境】
  • eval-source-map
  • eval-cheap-module-source-map
  • eval-cheap-source-map
  • eval 【建議開發環境用這個】

就能夠把打包後的代碼變成和開發的時候同樣
直接在文件webpack.config.js進行引入

devtool :'source-map', //更容易地追蹤錯誤和警告,方便在瀏覽器看見編譯以前的代碼,而非編譯以後的
// 一、source-map:產生文件,產生行列
// 二、eval-source-map:不產生文件,產生行類
// 三、cheap-source-map:產生文件,不產生列
// 四、cheap-module-eval-source-map:不產生文件,不產生列

會打包生成.map文件方便調試。
image.png`

source-map詳情:https://www.webpackjs.com/configuration/devtool/

快速搭建本地運行環境

webpack-dev-server:啓動服務和支持熱替換做用

爲你提供了一個簡單的 web 服務器,而且可以實時從新加載(live reloading)。

npm install webpack-dev-server -D
 //安裝 webpack-dev-server

webpack.config.json文件設置以下:

devServer: {
        contentBase: path.join(__dirname, "./dist"), // 開服務器的根路徑,和output同目錄
        historyApiFallback: true, //這個配置屬性是用來應對返回404頁面時定向到特定頁面用的,任意的 404 響應均可能須要被替代爲 index.html
        host: '0.0.0.0', //設置服務器的主機號,默認是localhost
        port: 7000, //輸出端口號
        inline: true, //實時刷新 package.json文件scripts dev中添加--inline後能夠不須要添加
        hot: true, //熱替換功能 即不刷新頁面,只對於修改的部分進行調整。默認是不設置就是會刷新頁面
        compress: true, //這是一個布爾型的值,當它被設置爲true的時候對全部的服務器資源採用gzip壓縮
        overlay: true, //用於在瀏覽器輸出編譯錯誤的,默認是關閉的,須要手動打開
        stats: "errors-only", //這個配置屬性用來控制編譯的時候shell上的輸出內容,由於咱們並不須要全部的內容,而只是須要部分的如errors等
        open: true, // 自動打開瀏覽器
        proxy: {
             "/api": {
                 target: "http://localhost:3000",
                 pathRewrite: { "^/api": "" }
             }
         } //重定向是解決跨域的好辦法,當後端的接口擁有獨立的API,而前端想在同一個domain下訪問接口的時候,能夠經過設置proxy實現。
        //一個 「/api/users」地址的請求將被重定向到」http://10.10.10.10:3000/api/users「,若是不但願」api」在傳遞中被傳遞過去,可使用rewrite的方式實現。
    },

package.json文件設置以下:

"scripts": {
    "dev": "cross-env NODE_ENV=development webpack-dev-server --inline"
  }

image.png
我這邊只是作了簡單的配置而已,而後執行命令 npm run dev
這時候因爲設置了open 會自動打開瀏覽器訪問http://localhost:7000/
讀取你的頁面。
webpack-dev-server詳情:https://www.webpackjs.com/guides/development/#使用-webpack-dev-server

模塊熱替換(Hot Module Replacement 或 HMR)

模塊熱替換(Hot Module Replacement 或 HMR)是 webpack 提供的最有用的功能之一。它容許在運行時更新各類模塊,而無需進行徹底刷新。
模塊熱替換功能通常用於開發環境。
配置 devServer

devServer: { 
    contentBase: \[path.join(\_\_dirname, "dist")\], 
    compress: true, port: 9000, // 啓動端口號 
    hot: true, // 啓用 webpack 的模塊熱替換特性 
    inline: true, 
    publicPath: "/", // 和上文 output 的「publicPath」值保持一致 
}

配置 plugins

plugins: [ // 開啓全局的模塊熱替換(HMR)  
    new webpack.HotModuleReplacementPlugin(), 
    // 當模塊熱替換(HMR)時在瀏覽器控制檯輸出對用戶更友好的模塊名字信息  
    new webpack.NamedModulesPlugin()
]

熱替換詳情:https://www.webpackjs.com/guides/hot-module-replacement/

準備好所有工做,最後搭建vue的項目:

搭建Vue項目

npm install vue-loader vue-template-compiler vue-style-loader -D
npm install vue -S

vue-loader 做用解析.vue文件
vue-style-loader 做用解析.vue的css
vue-template\-compiler 做用編譯模板
vue 一個用於構建用戶界面漸進式的MVVM框架

安裝完畢後須要進行plugins的配置和loader的引入
loader配置:
注意:個人scss的loader中use的style-loader已經修改成vue-style-loader
我這裏app.vue當中使用的是scss的寫法,因此解析sass就行了

module: {
        rules: [
            // loader 讓 webpack 可以去處理那些非 JavaScript 文件(webpack 自身只理解 JavaScript)
            // style-loader 將 JS 字符串生成爲 style 節點
            // css-loader 將 CSS 轉化成 CommonJS 模塊
            // sass-loader 將 Sass 編譯成 CSS
            // less-loader 將 Less 編譯成 CSS
            {
                test: /\.css$/,
                use: [MiniCssExtractPlugin.loader, 'css-loader', 'postcss-loader'],
                exclude: /node_modules/ //去除沒必要要的構建
            },
            {
                test: /\.scss$/,
                use: ['vue-style-loader', 'css-loader', 'postcss-loader', 'sass-loader'],
                exclude: /node_modules/ //去除沒必要要的構建
            },
            {
                test: /\.less$/,
                use: ['vue-style-loader', 'css-loader', 'postcss-loader', 'less-loader'],
                exclude: /node_modules/ //去除沒必要要的構建
            },
            {
                test: /\.(png|jpeg|jpg|gif|svg)$/,
                use: [{
                    loader: 'url-loader',
                    options: {
                        limit: 11024,
                        fallback: {
                            loader: 'file-loader',
                            options: {
                                name: '[name].[hash:6].[ext]'
                            }
                        }
                    }
                }],
                exclude: /node_modules/
            },
            {
                test: /\.(woff|woff2|eot|ttf|otf)$/,
                use: [
                    'file-loader'
                ]
            },
            {
                test: /\.js$/,
                use: {
                    loader: 'babel-loader',
                    options: {
                        presets: ['@babel/preset-env'],
                        plugins: [
                            '@babel/plugin-transform-runtime'
                        ]
                    }
                },
                exclude: /node_modules/
            },
            {
                test: /\.vue$/,
                use: [
                    'vue-loader'
                ],
                exclude: /node_modules/
            }
        ]
    }

plugins配置:

const VueLoaderPlugin = require('vue-loader/lib/plugin');

plugins: [
    new VueLoaderPlugin()
]

最後進行測試,修改src目錄底下的index.js文件:

import img11 from './images/img_2.png';
import './css/test.scss';
import './css/test1.css';
import './css/test2.less';
import print from './print.js';
print();

import Vue from 'vue';
import App from './components/app.vue';
new Vue({
    el: '#app',
    render: h=>h(App)
})

修改index.html文件:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title><%= htmlWebpackPlugin.options.title %></title>
</head>
<body>
     <div id="app"></div>
     <script src="./dist/bundle.js"></script>
</body>
</html>

在src文件夾底下生成components文件夾新建app.vue

<template>
    <div class="app">
        <h1>3333</h1>
        <div>asdjklasjdlkas</div>
    </div>
</template>

<script>
    export default {
        
    }
</script>

<style lang="scss" scoped>
.app{
    h1{
        color: red;
    }
}
</style>

最後目錄以下:
image.png

npm run dev 編譯啓動瀏覽器讀取文件,熱替換

大功告成!!!!!

總結一下:

項目運行

  • npm i安裝依賴
  • npm run dll構建出不需打包的vendor包
  • npm run build構建打包

entry 入口文件

output 出口文件名及路徑

webpack-dev-server能夠開啓本地服務器,或者設置proxy代理

source-map 能夠生成.map文件,方便調試

mode取值development或者production,production模式下js會自動壓縮

loader與plugin

  • html-webpack-plugin 能夠將打包後的資源自動引入到html中
  • style-loader css-loader能夠支持css模塊
  • sass-loader node-sass 能夠支持sass
  • less-loader 能夠支持less
  • postcss-loader autoprefixer 能夠支持自動加css前綴
  • mini-css-extract-plugin 或者 extract-text-webpack-plugin能夠支持css從js中抽離
  • optimize-css-assets-webpack-plugin 能夠壓縮css
  • purify-css purifycss-webpack 能夠去除無用的css
  • babel-loader @babel/core 能夠支持es6語法
  • @babel/preset-env 是根據瀏覽器或者運行環境來將es6轉化成es5,好比根據browserslist
  • 補充說明1:@babel/polyfill 是對es6降級es5的一個墊片,是對babel-loader的補充,可是會污染全局,不能按需引入,不建議這種方式
  • 補充說明2:@babel/runtime @babel/plugin-transform-runtime也是對es6降級es5的一個墊片,能夠按需引入,模塊化加載,不污染全局,推薦使用
  • file-loader 或者 url-loader能夠支持引入文件
  • file-loader不支持小文件轉化爲base64格式,可是能夠爲文件名添加hash值,url-loader能夠支持小文件轉化爲base64格式,這兩個能夠搭配使用
  • vue-loader vue-template-compiler 能夠支持編譯.vue文件
  • clean-webpack-plugin 能夠清除打包後的文件夾
  • webpack.HotModuleReplacementPlugin webpack自帶的熱替換plugin與devServer的hot:true結合使用,使頁面能夠不刷新

源碼:https://github.com/MaxFung3t/webpack-test

相關文章
相關標籤/搜索