<span id="mktg5"></span>

<i id="mktg5"><meter id="mktg5"></meter></i>

        <label id="mktg5"><meter id="mktg5"></meter></label>
        最新文章專題視頻專題問答1問答10問答100問答1000問答2000關鍵字專題1關鍵字專題50關鍵字專題500關鍵字專題1500TAG最新視頻文章推薦1 推薦3 推薦5 推薦7 推薦9 推薦11 推薦13 推薦15 推薦17 推薦19 推薦21 推薦23 推薦25 推薦27 推薦29 推薦31 推薦33 推薦35 推薦37視頻文章20視頻文章30視頻文章40視頻文章50視頻文章60 視頻文章70視頻文章80視頻文章90視頻文章100視頻文章120視頻文章140 視頻2關鍵字專題關鍵字專題tag2tag3文章專題文章專題2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章專題3
        問答文章1 問答文章501 問答文章1001 問答文章1501 問答文章2001 問答文章2501 問答文章3001 問答文章3501 問答文章4001 問答文章4501 問答文章5001 問答文章5501 問答文章6001 問答文章6501 問答文章7001 問答文章7501 問答文章8001 問答文章8501 問答文章9001 問答文章9501
        當前位置: 首頁 - 科技 - 知識百科 - 正文

        搭建vue2vue-router2webpack3工程教程

        來源:懂視網 責編:小OO 時間:2020-11-27 20:05:53
        文檔

        搭建vue2vue-router2webpack3工程教程

        以新手視角,詳細介紹各個步驟內容,不深入講步驟涉及的原理,主要介紹如何操作。初始化工程;新建工程目錄 vue2practice,在目錄下執行npm init -y來創建一個 package.json,在 package.json 中先添加以下必備模塊。
        推薦度:
        導讀以新手視角,詳細介紹各個步驟內容,不深入講步驟涉及的原理,主要介紹如何操作。初始化工程;新建工程目錄 vue2practice,在目錄下執行npm init -y來創建一個 package.json,在 package.json 中先添加以下必備模塊。
        本文主要介紹了詳解從零搭建 vue2 vue-router2 webpack3 工程,小編覺得挺不錯的,現在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧。希望能幫助到大家。

        以新手視角,詳細介紹各個步驟內容,不深入講步驟涉及的原理,主要介紹如何操作。

        初始化工程

        新建工程目錄 vue2practice,在目錄下執行npm init -y來創建一個 package.json,在 package.json 中先添加以下必備模塊:

        {
        
         "name": "vue2-vue-router2-webpack3",
        
         "version": "1.0.0",
        
         "devDependencies": {
        
         "vue": "^2.4.2",
        
         "vue-loader": "^13.0.2",
        
         "vue-router": "^2.7.0",
        
         "vue-template-compiler": "^2.4.2",
        
         "webpack": "^3.4.1",
        
         "webpack-dev-server": "^2.6.1"
        
         }
        
        }

        其中 vue-template-compiler 是 vue-loader 的 peerDependencies,npm3 不會自動安裝 peerDependencies,然而 vue-template-compiler 又是必備的,那為什么作者不將其放到 dependencies 中呢?有人在 github 上提過這個問題,我大致翻譯一下作者的回答(僅供參考):這樣做的原因是因為沒有可靠的方式來固定嵌套依賴的關系,怎么理解這句話?首先 vue-template-compiler 和 vue 的版本號是一致的(目前是同步更新),將 vue-template-compiler 指定為 vue-loader 的 dependencies 并不能保證 vue-template-compiler 和 vue 的版本號是相同的,讓用戶自己指定版本才能保證這一點。查看作者的回答(英文) 。如果兩者版本不一致,運行時會出現下圖所示的錯誤提示。

        新建目錄結構如下,新增的目錄及文件先空著,后面的步驟會說明添加什么內容。

        vue2pratice
        
         |-- package.json
        
         |-- index.html // 啟動頁面
        
         |-- webpack.config.js // webpack配置文件
        
         |-- src
        
         |-- views // vue頁面組件目錄
        
         |-- main.js // 入口文件
        
         |-- router.js // vue-router配置
        
         |-- app.vue // 工程首頁組件

        配置Webpack

        Webpack 默認讀取 webpack.config.js,文件名不能隨便改,其中 entry 是必須配置的。

        module.exports = {
        
         entry: './src/main.js',
        
         output: {
        
         path: __dirname + '/dist',
        
         publicPath: '/static/',
        
         filename: 'build.js'
        
         }
        
        }

        Webpack 2+ 要求output.path必須為絕對路徑。

        配置 webpack-dev-server,只需在 package.json 添加以下啟動命令即可。

        "scripts": {
        
         "dev": "webpack-dev-server --hot --open"
        
        }

        webpack-dev-server 2 默認為 inline 模式,熱模塊替換仍需自己設置。

        驗證配置

        在 index.html 中添加測試代碼,引入打包后的 JS 文件。

        <body>
        
         Hello, Webpack 3.
        
         <br>
        
         <script src="/static/build.js"></script>
        
        </body>

        在 main.js 中添加測試代碼。

        // main.js
        
        document.write('來自main.js的問候!')

        執行下面的命令來安裝模塊并啟動服務器。

        // 安裝依賴
        
        npm install
        
         
        
        // 運行
        
        npm run dev

        啟動后瀏覽器會自動打開http://localhost:8080,如果控制臺沒有報錯,頁面正確顯示 main.js 和 index.html 的內容,改動 main.js 后瀏覽器不刷新能看到效果,則表示配置沒問題。

        Vue

        新建頁面

        在 views 目錄下新建 index.vue。

        <template>
        
         <p>
        
         這是{{page}}頁面
        
         </p>
        
        </template>
        
        <script>
        
        export default {
        
         data: function () {
        
         return {
        
         page: 'index'
        
         }
        
         }
        
        }
        
        </script>

        webpack 1 需要特定的 loader 來轉換 ES 2015 import/export,webpack 2 起可以開箱即用。但是 ES6 的新語法還是需要 loader 來轉換,在沒有配置前,先不要用新語法。用了也沒報錯(比如 let,const等),那是因為你的瀏覽器已經支持了 ES6 語法(新版本瀏覽器都已經支持)。

        配置路由

        將 vue-router 實例化傳入的參數new VueRouter(參數)提取到 router.js 形成路由配置文件。

        import index from './views/index.vue'
        
        export default {
        
         routes: [
        
         {
        
         path: '/index',
        
         component: index
        
         }
        
         ]
        
        }

        從 vue-loader@13.0.0,不能用 require 來引入 .vue 文件,因為 .vue 文件最終會被編譯成 ES6 module。

        首頁

        首頁引入 ouput 配置的 JS,添加 Vue 實例的掛載目標。

        <body>
        
        <p id="app"></p>
        
        <script src="/static/build.js"></script>
        
        </body>

        入口JS完成路由配置、初始化 Vue 實例。

        import Vue from 'vue';
        
        import VueRouter from 'vue-router';
        
        import App from './app.vue';
        
        import routerConfig from './router';
        
        Vue.use(VueRouter);
        
        var router = new VueRouter(routerConfig)
        
        new Vue({
        
         el: '#app',
        
         router: router,
        
         render: h => h(App)
        
        });

        從 Vue 2.2.0 后使用 require('vue') 會報錯,應使用 ES6 module(import),具體原因請參考 Vue 更新說明 https://github.com/vuejs/vue/releases,截圖如下:

        在首頁組件 app.vue 中添加路由鏈接、路由視圖組件。

        <template>
        
         <p>
        
         <p>
        
         <router-link to="/index">Home</router-link>
        
         </p>
        
         <p>
        
         <router-view></router-view>
        
         </p>
        
         </p>
        
        </template>

        配置loader

        配置 vue 文件對應的 loader。

        module: {
        
         rules: [
        
         {
        
         test: /\.vue$/,
        
         use: ["vue-loader"]
        
         }
        
         ]
        
        }

        Webpack2 必須在 module.rules 下配置 loader。'-loader'不能省略,必須將 loader 名寫全。可以使用 Rule.use 或 Rule.loader 來配置 loader(Rule.loader 是 Rule.use: [ { loader } ] 的簡寫),建議用 use。

        上面完成了新增頁面及訪問該頁面所需的配置,下面來測試下是否能正常訪問/index。執行npm run dev,瀏覽器顯示如圖界面。

        支持CSS

        安裝 css-loader 后即可在 vue 文件中使用

        npm i css-loader -D

        想要支持import / require引入CSS文件,則需要配置對應的 Rule。

        {
        
         test: /\.css$/,
        
         use: ["vue-style-loader", "css-loader"]
        
        }
        <script>
        
        import "../style/style.css"
        
        </script>

        支持CSS預處理語言

        以 stylus 為例,安裝 stylus 及 stylus-loader。

        npm install stylus stylus-loader -D

        增加 .styl 文件對應的 loader 配置。

        {
        
         test: /\.styl$/,
        
         use: ["vue-style-loader", "css-loader", "stylus-loader"]
        
        }

        使用示例:

        <style lang="stylus">
        
         .stylus
        
         .red
        
         color red
        
        </style>
        
        <script>
        
         import "../css/stylus-example.styl"
        
        </script>

        node-sass 安裝慢的解決辦法

        使用淘寶鏡像:

        npm set disturl https://npm.taobao.org/dist

        也可以單獨設置node-sass鏡像:

        npm set sass_binary_site http://cdn.npm.taobao.org/dist/node-sass

        支持圖片及圖標字體

        安裝圖片及圖標字體依賴的loader。

        npm install url-loader file-loader -D

        增加圖片及圖標字體的loader配置。

        {
        
         test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
        
         use: [{
        
         loader: "url-loader",
        
         options: {
        
         limit: 10000,
        
         name: 'images/[name].[hash:7].[ext]' // 將圖片都放入images文件夾下,[hash:7]防緩存
        
         }
        
         }]
        
        },
        
        {
        
         test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
        
         use: [{
        
         loader: "url-loader",
        
         options: {
        
         limit: 10000,
        
         name: 'fonts/[name].[hash:7].[ext]' // 將字體放入fonts文件夾下
        
         }
        
         }]
        
        }

        構建

        添加打包命令如下:

        "build":"webpack --progress --colors"

        執行npm run build開始構建,完成后,可以看到工程目錄下多了dist目錄以及 dist/build.js。

        使用 Webpack 插件

        壓縮JS

        在之前的文章提到過,打開未壓縮版的build.js,你會發現ES6的語法沒有被轉化為ES5,因此需要安裝babel 套件來完成語法的轉化,否則壓縮的時候就會報錯。之前廣泛使用的轉碼規則為 babel-preset-es2015,但 Babel 的官網上在9月宣布 ES2015 / ES2016/ ES2017 等等 ES20xx 時代的 presets 通通被廢棄(deprecated),取而代之的是 babel-preset-env,并且承諾它將成為“未來不會過時的(future-proof)”解決方案。

        npm i babel-loader babel-core babel-preset-env -D

        增加babel的配置文件.babelrc。

        {
        
         "presets": [
        
         ["env", { "modules": false }]
        
         ],
        
         "comments": false
        
        }

        將 modules 設置為 false,即交由 Webpack 來處理模塊化,通過其 TreeShaking 特性將有效減少打包出來的 JS 文件大小,可以自行對比下前后打包出來的文件的大小,效果還是不錯的。

        comments 即是否保留注釋。

        接著配置 JS 文件的 loader。

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

        注意:Webpack2建議盡量避免exclude,更傾向于使用include。

        壓縮 JS 采用webpack.optimize.UglifyJsPlugin,配置如下:

        new webpack.optimize.UglifyJsPlugin()

        官網稱warnings默認為false,你可能會遇到即使沒有配置warnings: true,控制臺仍顯示警告,看下面這段源碼就知道了。查看源碼

        只有當options.compress !== false時 warnings 才會被設置默認值 false,所以一旦配置了 compress 其它選項,那就需同時配置warnings: false。

        warnings作用是當插件在壓縮過程中移除的無效代碼或定義是顯示警告信息(display warnings when dropping unreachable code or unused declarations etc.)。

        提取CSS

        使用extract-text-webpack-plugin插件提取CSS。更改 css 及 less 的 loader 配置如下。

        // 安裝插件
        
        npm i extract-text-webpack-plugin -D
        // var ExtractTextPlugin = require("extract-text-webpack-plugin")
        
        {
        
         test: /\.css$/,
        
         use: ExtractTextPlugin.extract({
        
         use: "css-loader"
        
         })
        
        },
        
        {
        
         test: /\.styl$/,
        
         use: ExtractTextPlugin.extract({
        
         use: ["css-loader", "stylus-loader"]
        
         })
        
        }

        上述配置并不能提取 vue 文件中的 style,需要設置 vue-loader 參數才可以。

        {
        
         test: /\.vue$/,
        
         use: {
        
         loader: "vue-loader",
        
         options: {
        
         loaders: {
        
         css: ExtractTextPlugin.extract({
        
         use: 'css-loader'
        
         }),
        
         stylus: ExtractTextPlugin.extract({
        
         use: ["css-loader", "stylus-loader"]
        
         })
        
         }
        
         }
        
         }
        
        }

        初始化插件,filename 可以指定 CSS 文件的目錄。

        new ExtractTextPlugin({
        
         filename: "css/style.css"
        
        })

        PostCSS

        安裝 postcss-loader 及 postcss 插件。

        npm i postcss-loader cssnano -D

        配置 loader 如下:

        // css-loader配置改為
        
        use: ['css-loader', "postcss-loader"]
        
        // stylus-loader配置改為
        
        use: ["css-loader", "postcss-loader", "stylus-loader"]

        postcss-loader 要放在 css-loader 和 style-loader 之后,CSS 預處理語言 loader 之前(stylus-loader)。

        新增 postcss.config.js 來配置postcss插件,這樣就不用給每個 postcss-loader 去配置。更多 postcss-loader 的配置方式請參考 postcss-load-config。

        module.exports = {
        
         plugins: [
        
         require('cssnano')
        
         ]
        
        }

        cssnano 使用了一系列 postcss 插件,包含了常用的 autoprefixer 等,如何傳入 autoprefixer 的配置?

        require('cssnano')({
        
         autoprefixer: {
        
         add: true,
        
         browsers: ['> 5%']
        
         }
        
        })

        其中有一個插件 postcss-zindex 使用中發現有些問題。如果想禁用這個插件的話,配置如下:

        require('cssnano')({
        
         zindex: {
        
         disable:true
        
         }
        
        })

        附:postcss插件分類搜索網站:http://postcss.parts/

        生成首頁

        安裝 html-webpack-plugin 插件。

        npm i html-webpack-plugin -D

        初始化插件。

        // var HtmlWebpackPlugin = require('html-webpack-plugin');
        
        new HtmlWebpackPlugin({
        
         filename: 'index.html',
        
         template: 'index.tpl.html'
        
        })

        其它插件

        Webpack3 新增的作用域提升。

        new webpack.optimize.ModuleConcatenationPlugin()

        指定生產環境,以便在壓縮時可以讓 UglifyJS 自動刪除代碼塊內的警告語句。

        new webpack.DefinePlugin({
        
         'process.env.NODE_ENV': JSON.stringify('production')
        
        })

        因為這個插件直接做的文本替換,給定的值必須包含字符串本身內的實際引號。通常,有兩種方式來達到這個效果,使用 '"production"', 或者使用 JSON.stringify('production')。

        你完全可以在自己的代碼中使用process.env.NODE_ENV來區分開發和生產,從而針對不同的環境做一些事情。不用擔心這部分代碼會被保留,最終會被 UglifyJS 刪除。例如:

        if (process.env.NODE_ENV != "production") {
        
         // 開發環境
        
        }
        
        // webpack.DefinePlugin插件替換后,上述代碼會變成
        
        if ("production" != "production") {
        
         // 開發環境
        
        }
        
        // 
        輸出 if (false) { // 開發環境 } // UglifyJS 會刪除這段無效代碼

        使用上述插件后再次構建,會發現生成的JS相比原來的體積小了不少。

        friendly-errors-webpack-plugin 是一個更友好顯示 webpack 錯誤信息的插件。插件 github 地址:https://github.com/geowarin/friendly-errors-webpack-plugin

        一般在開發環境下使用。

        var FriendlyErrorsWebpackPlugin = require('friendly-errors-webpack-plugin');
        
         
        
        var webpackConfig = {
        
         // ...
        
         plugins: [
        
         new FriendlyErrorsWebpackPlugin(),
        
         ],
        
         // ...
        
        }

        效果如下圖:

        顯示構建進度插件:webpack.ProgressPlugin

        {
        
         // ...
        
         plugins: [
        
         new webpack.ProgressPlugin(),
        
         ],
        
         // ...
        
        }

        效果如下圖:

        美化 webpack 編譯控制臺打印的信息的插件webpack-dashboard

        分離Webpack配置

        將開發和生產配置文件分離,方便增加各個環境下的個性配置。Webpack2文檔中也詳細闡述了如何為多環境配置webpack?;舅悸啡缦拢?/p>

        1. 編寫一個基本配置文件(webpack.base.config.js)

        2. 使用webpack-merge合并這個基礎配置和針對環境的特定的配置(webpack.dev.config.js,webpack.prod.config.js)

        webpack.base.config.js 內容如下:

        var webpack = require('webpack');
        
        var path = require('path');
        
        var utils = require('./utils');
        
        function resolve(relPath) {
        
         return path.resolve(__dirname, relPath);
        
        }
        
        module.exports = {
        
         entry: { app: resolve('../src/main.js') },
        
         output: {
        
         filename: 'js/[name].js'
        
         },
        
         module: {
        
         rules: [{
        
         test: /\.js$/,
        
         use: "babel-loader",
        
         include: [resolve('../src')]
        
         },
        
         {
        
         test: /\.vue$/,
        
         use: {
        
         loader: "vue-loader",
        
         options: utils.vueLoaderOptions()
        
         }
        
         },
        
         {
        
         test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
        
         use: {
        
         loader: "url-loader",
        
         options: {
        
         limit: 10000,
        
         name: 'images/[name].[hash:7].[ext]'
        
         }
        
         }
        
         },
        
         {
        
         test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
        
         use: [{
        
         loader: "url-loader",
        
         options: {
        
         limit: 10000,
        
         name: 'fonts/[name].[hash:7].[ext]'
        
         }
        
         }]
        
         }
        
         ]
        
         }
        
        }

        為什么要將vue-loader的options提取出來?其主要是用來配置CSS及CSS預處理語言的loader,開發環境可以不用配置,但是生產環境需要提取CSS、增加postcss-loader等,因此需要提取出來針對不同環境返回相應的options。后面會列出utils.vueLoaderOptions的內容。

        為什么沒有配置CSS的loader?理由和上面的vue-loader一樣。

        為什么沒有配置path和publicPath?一方面是個性化參數,另外開發和生產可能不相同,因此在webpack.dev.config和webpack.prod.config中分別配置更為合適。

        webpack.dev.config.js 內容如下:

        var webpack = require('webpack');
        
        var merge = require('webpack-merge');
        
        var HtmlWebpackPlugin = require('html-webpack-plugin');
        
        var baseWebpackConfig = require('./webpack.base.config');
        
        var utils = require('./utils');
        
        var config = require('./config');
        
        Object.keys(baseWebpackConfig.entry).forEach(function(name) {
        
         baseWebpackConfig.entry[name] = [
        
         `webpack-dev-server/client?http://localhost:${config.dev.port}/`,
        
         "webpack/hot/dev-server"
        
         ].concat(baseWebpackConfig.entry[name])
        
        });
        
        module.exports = merge(baseWebpackConfig, {
        
         output: {
        
         path: config.dev.outputPath,
        
         publicPath: config.dev.outputPublicPath
        
         },
        
         module: {
        
         rules: utils.styleLoaders()
        
         },
        
         plugins: [
        
         new webpack.HotModuleReplacementPlugin(),
        
         new HtmlWebpackPlugin({
        
         filename: 'index.html',
        
         template: 'index.html',
        
         inject: true
        
         })
        
         ]
        
        })

        添加了HtmlWebpackPlugin后,index.html中就不需要在自己去引用打包的JS了,會自動根據打包的JS添加引用,這樣更加方便,關于HtmlWebpackPlugin的配置,需要說明兩點:

        1.template的路徑是相對于webpack編譯時的上下文目錄,說白了就是項目根目錄,因此上面可以直接配置index.html,其指向的就是根目錄下的index.html;

        2.filename則是相對于webpack配置項output.path(打包資源存儲路徑)。

        html-webpack-plugin關于template和filename路徑源碼如下:

        // https://github.com/jantimon/html-webpack-plugin/blob/master/index.js
        
        // template
        
        this.options.template = this.getFullTemplatePath(this.options.template, compiler.context);
        
        // filename
        
        this.options.filename = path.relative(compiler.options.output.path, filename);

        config.js內容如下:

        module.exports = {
        
         dev: {
        
         outputPath: path.resolve(__dirname, '../static'),
        
         outputPublicPath: '/',
        
         port: 8000
        
         },
        
         prod: {
        
         outputPath: path.resolve(__dirname, '../static'),
        
         outputPublicPath: '/static/'
        
         }
        
        }

        utils.js內容如下:

        var ExtractTextPlugin = require('extract-text-webpack-plugin');
        
        var isProd = process.env.NODE_ENV === "production";
        
        // 根據項目需求添加CSS預處理語言并安裝相應的loader,以stylus-loader為例
        
        var cssLang = [{
        
         name: 'css',
        
         reg: /\.css$/,
        
         loader: 'css-loader'
        
        }, {
        
         name: 'stylus',
        
         reg: /\.styl$/,
        
         loader: "stylus-loader"
        
        }];
        
        function genLoaders(lang) {
        
         var loaders = ['css-loader', 'postcss-loader'];
        
         if (lang.name !== 'css') {
        
         loaders.push(lang.loader);
        
         }
        
         if (isProd) {
        
         // 生產環境需要提取CSS
        
         loaders = ExtractTextPlugin.extract({
        
         use: loaders
        
         });
        
         } else {
        
         // 開發環境需要vue-style-loader將CSS提取到頁面頭部
        
         loaders.unshift('vue-style-loader');
        
         }
        
         return loaders;
        
        }
        
        // 各種CSS的loader
        
        exports.styleLoaders = function() {
        
         var output = [];
        
         cssLang.forEach(lang => {
        
         output.push({
        
         test: lang.reg,
        
         use: genLoaders(lang)
        
         })
        
         })
        
         return output;
        
        };
        
        // vue-loader的options
        
        exports.vueLoaderOptions = function() {
        
         var options = {
        
         loaders: {}
        
         };
        
         cssLang.forEach(lang => {
        
         options.loaders[lang.name] = genLoaders(lang);
        
         });
        
         return options;
        
        }

        接下來就是如何啟動webpack-dev-server,vue-cli的webpack模板工程用的express及webpack中間件做開發服務器,其實用webpack-dev-server就能滿足需求,當然用express能夠做更多的事情,畢竟webpack-dev-server是一個輕量級的express。dev.js內容如下:

        var webpack = require('webpack');
        
        var webpackDevServer = require('webpack-dev-server');
        
        var devConfig = require("./webpack.dev.config");
        
        var config = require("./config");
        
        var compiler = webpack(devConfig);
        
        var server = new webpackDevServer(compiler, {
        
         hot: true,
        
         noInfo: true,
        
         publicPath: config.dev.outputPublicPath,
        
         stats: { colors: true }
        
        });
        
        server.listen(config.dev.port, "0.0.0.0");
        
        var url = `http://localhost:${config.dev.port}/`;
        
        // 需先安裝 opn 模塊 npm i opn -D
        
        var opn = require('opn');
        
        // 打包完畢后啟動瀏覽器
        
        server.middleware.waitUntilValid(function() {
        
         console.log(`> Listening at ${url}`);
        
         opn(`${url}`);
        
        })

        生產配置文件(webpack.prod.config.js)內容如下:

        // 設定為生產環境
        
        process.env.NODE_ENV = 'production';
        
        var webpack = require('webpack');
        
        var merge = require('webpack-merge');
        
        var HtmlWebpackPlugin = require('html-webpack-plugin');
        
        var ExtractTextPlugin = require('extract-text-webpack-plugin');
        
        var baseWebpackConfig = require('./webpack.base.config');
        
        var utils = require('./utils');
        
        var config = require('./config');
        
         
        
        module.exports = merge(baseWebpackConfig, {
        
         output: {
        
         path: config.prod.outputPath,
        
         publicPath: config.prod.outputPublicPath
        
         },
        
         module: {
        
         rules: utils.styleLoaders()
        
         },
        
         plugins: [
        
         new webpack.DefinePlugin({
        
         'process.env.NODE_ENV': '"production"'
        
         }),
        
         new webpack.optimize.UglifyJsPlugin(),
        
         new ExtractTextPlugin({
        
         filename: "css/style.css?[contenthash:8]"
        
         }),
        
         new HtmlWebpackPlugin({
        
         filename: 'index.html',
        
         template: 'index.html',
        
         inject: true
        
         })
        
         ]
        
        })

        生產構建(prod.js)內容如下:

        var webpack = require("webpack");
        
        var webpackProdConfig = require('./webpack.prod.config');
        
        webpack(webpackProdConfig, function(err, stats) {
        
         process.stdout.write(stats.toString());
        
        });

        對應在package.json中添加開發和生產構建的命令如下:

        "scripts": {
        
         "dev": "node build/dev.js",
        
         "build": "node build/prod.js"
        
        }

        代碼分割

        參照vue-cli及webpack文檔的提取公共代碼的方式,利用插件webpack.optimize.CommonsChunkPlugin將來自node_modules下的模塊提取到vendor.js(一般來講都是外部庫,短時間不會發生變化)。于是有如下代碼:

        new webpack.optimize.CommonsChunkPlugin({
        
         name: 'vendor',
        
         minChunks: function(module, count) {
        
         return module.resource && /\.js$/.test(module.resource) && module.resource.indexOf(path.join(__dirname, '../node_modules')) === 0
        
         }
        
        })

        如果你查看未壓縮版的vendor.js,會發現不僅包含vue的代碼,還包含了webpackBootstrap(webpack模塊加載器)的代碼,按理說放在vendor里面也沒啥問題,畢竟后面的模塊都需要依賴于此,但是如果你的chunk使用了hash,一旦app代碼發生了改變,相應的hash值會發生變化,webpackBootstrap的代碼也會發生變化(如圖),而我們提取vendor的初心就是這部分代碼改變頻率不大,顯然這不符合我們的目標,那么應當將webpackBootstrap再提取到一個文件中,代碼如下:

        new webpack.optimize.CommonsChunkPlugin({
        
         name: 'manifest',
        
         chunks: ['vendor']
        
        })


        用 import 還是 require

        vue 2.2.0 后不能直接使用 require 來加載 vue,那么到底改是該使用 ES6 Module 還是 CommonJS 呢?,先看一個對比圖:

        全部使用 ES6 Module,即import、export default,最終打包的app.js為1.20KB。

        全部使用 CommonJS(除了vue),即require、module.exports,最終打包的app.js為1.12KB。

        雖然兩者大小相差不大,但是這不禁讓人覺得用 CommonJS 似乎是一條優化措施,那么代碼層面到底是怎么回事呢?

        為了一探究竟,注釋了壓縮插件,以about.vue最終構建的代碼來看,使用 CommonJS 的代碼如下:

         (function (module, exports, __webpack_require__) {
        
         "use strict";
        
         module.exports = {
        
         data: function data() {
        
         return {
        
         page: 'about'
        
         };
        
         }
        
         };
        
        }),

        這基本上和 about.vue 中的代碼相差無幾,而使用 ES6 Module 構建的代碼如下:

        (function (module, exports, __webpack_require__) {
        
         "use strict";
        
         Object.defineProperty(exports, "__esModule", {
        
         value: true
        
         });
        
         exports.default = {
        
         data: function data() {
        
         return {
        
         page: 'about'
        
         };
        
         }
        
         };
        
        }),

        對比兩種規范下構建后的代碼,使用 ES6 Module 主要是多了 Object.defineProperty 那一部分,從而導致了最終打包的文件大一點兒。那是不是為了最終文件體積能小些就全部使用 CommonJS 呢?這個需要你充分理解 CommonJS 和 ES6 Module 的區別,引用《ECMAScript 6入門》這本書的解釋如下:

        ES6模塊加載的機制,與CommonJS模塊完全不同。CommonJS模塊輸出的是一個值的拷貝,而ES6模塊輸出的是值的引用。

        為了更清楚的理解這段話,我們稍微做一下測試,在 src 下增加一個test.js,內容如下(分別將兩種寫法列出):

        // CommonJS
        
        var counter = 1;
        
        function incCounter() {
        
         counter++;
        
        }
        
        module.exports = {
        
         counter: counter,
        
         incCounter: incCounter,
        
        };
        
        // ES6 Module
        
        export let counter = 1;
        
        export function incCounter() {
        
         counter++;
        
        }

        在about.vue中測試如下:

         // CommonJS
        
        var test = require('../test');
        
        export default {
        
         created() {
        
         console.log(test.counter); // 1
        
         test.incCounter();
        
         console.log(test.counter); // 1
        
         }
        
        }
        
        // ES6 Module
        
        import { counter, incCounter } from '../test';
        
        export default {
        
         created() {
        
         console.log(counter); // 1
        
         incCounter();
        
         console.log(counter); // 2
        
         }
        
        }

        最終的輸出值也印證了前面的解釋,更詳細的解讀請查閱相關資料或書籍。只有深入理解了兩者的區別,自然就能明白何時該使用何種規范。當然 ES6 作為未來的趨勢,我們應該去做更多的嘗試。

        異步組件(懶加載)

        之前用懶加載的方式是:require.ensure,在 webpack2 中引入了 Code Splitting-Async 的新方法 import(),用于動態引入 ES Module。require.ensure 可以指定 chunkFilename,但是 import 沒有很好的途徑去指定,webpack3 為了解決這個問題,提出了用魔法注釋的方式來指定模塊名。

        結合 vue-router 可以輕松實現懶加載,配置路由指向異步組件即可實現懶加載,比如:

        {
        
         path: '/async',
        
         component: () => import(/* webpackChunkName: "async" */'./views/async.vue')
        
        }

        如果你發現使用 import() 運行時報錯,有幾種情況:
        1.babel presets 配置為 es2015,則不支持動態導入功能,因此需要安裝支持動態導入的 presets(npm i babel-preset-stage-2 -D),或者 babel 插件(npm i babel-plugin-syntax-dynamic-import -D);
        2.babel presets 配置為 env,但是 modules 配置為 false,babel 則不會解析 import,可以安裝插件 (npm i babel-plugin-syntax-dynamic-import -D)解決。

        魔法注釋雖然指定了塊名,但是 webpack 默認的塊名配置為 [id].js,即用的模塊的 id 作為塊名,因此需要我們手動改下配置。

        修改 webpack.base.config.js 的 output:

        output: {
        
         filename: 'js/[name].js',
        
         chunkFilename: "js/[name].[chunkhash].js"
        
        }

        效果如下圖:

        如果發現魔法注釋沒有生效,要檢查下 .babelrc 的配置項 comments 是否設為 true?;蛘卟慌渲?comments(默認為true)

        extract-text-webpack-plugin 默認不會提取異步模塊中的 CSS,需要加上配置:

        new ExtractTextPlugin({
        
         allChunks:true,
        
         filename: "css/style.css?[contenthash:8]"
        
        })

        聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com

        文檔

        搭建vue2vue-router2webpack3工程教程

        以新手視角,詳細介紹各個步驟內容,不深入講步驟涉及的原理,主要介紹如何操作。初始化工程;新建工程目錄 vue2practice,在目錄下執行npm init -y來創建一個 package.json,在 package.json 中先添加以下必備模塊。
        推薦度:
        標簽: 創建 VUE 工程
        • 熱門焦點

        最新推薦

        猜你喜歡

        熱門推薦

        專題
        Top
        主站蜘蛛池模板: 七色永久性tv网站免费看| 亚洲国产精品久久久久网站| ass亚洲**毛茸茸pics| 最近免费中文字幕高清大全| 亚洲天堂中文资源| 久久精品无码专区免费青青| 久久精品亚洲一区二区三区浴池| 久久久精品免费视频| 久久久久亚洲AV无码观看| 在免费jizzjizz在线播 | 亚洲男人的天堂www| 国产精品午夜免费观看网站| 国产亚洲美日韩AV中文字幕无码成人| 和老外3p爽粗大免费视频| 亚洲AV永久精品爱情岛论坛| 91精品国产免费久久国语蜜臀| 337p日本欧洲亚洲大胆艺术| 97在线观免费视频观看 | 亚洲av日韩av不卡在线观看 | 午夜在线亚洲男人午在线| 免费在线观看你懂的| aa在线免费观看| 亚洲综合精品一二三区在线| 久久午夜免费视频| 国产亚洲综合视频| 亚洲无线码在线一区观看| 亚洲黄色免费观看| 美女被免费网站在线视频免费| 亚洲中文字幕在线观看| 五月亭亭免费高清在线| 无码天堂亚洲国产AV| 亚洲av永久无码精品古装片| 亚洲免费网站观看视频| 亚洲精品黄色视频在线观看免费资源| 亚洲av日韩av激情亚洲| 国产一级淫片a视频免费观看| 久久久久久久99精品免费观看 | 亚洲一级片在线观看| 亚洲AV蜜桃永久无码精品| 99视频有精品视频免费观看| 亚洲日韩国产AV无码无码精品|