webpack實戰(zhàn)之(手把手教你從0開始搭建一個vue項目)

前言

我們前面從前端架構(gòu):

到項目工程化工具eslint沐悦、babel、webpack等,分別結(jié)合demo跟源碼做了具體的分析:

接下來我們把前面的所有知識點來實戰(zhàn)一下美尸,就當成前面所有知識點的一個總結(jié)了执虹。

需求

我們都知道,當我們用react開發(fā)一個項目的時候,我們可以用官方的腳手架Create React App育瓜,當我們用vue開發(fā)一個項目的時候青自,我們也可以用官方的腳手架vue-cli, 用起來是真的爽爸暌馈!也不需要自己去配置eslint延窜、babel恋腕、webpack等等,腳手架會根據(jù)你的選擇自動幫你完成配置逆瑞,是的荠藤! 一般項目都可以覆蓋到伙单,但是如果想要用好這些腳手架的話我們還是需要了解其中的一些配置的原理的。

我們這一次實戰(zhàn)demo的需求是這樣的:

  • js框架(vue哈肖、typescript吻育、tsx、jsx)
  • css樣式(sass)
  • 工程化工具(eslint淤井、babel布疼、webpack、webpack-chain)

ok币狠!這差不多算是一個比較復雜的項目了缎除,接下來我們一步步來實現(xiàn)一下它。

開始

我們直接創(chuàng)建一個項目叫webpack-vue-demo总寻,然后進到項目根目錄執(zhí)行npm init:

webpack-vue-demo npm init
    ...
Is this OK? (yes) 
?  webpack-vue-demo 

webpack腳手架

創(chuàng)建完畢后器罐,我們首先安裝webpack相關(guān)依賴:

webpack(webpack框架)

yarn add -D webpack || npm install -D webpack

webpack-cli(webpack腳手架)

yarn add -D webpack-cli || npm install -D webpack-cli

webpack-dev-server(webpack開發(fā)環(huán)境)

yarn add -D webpack-dev-server || npm install -D webpack-dev-server

webpack-chain(webpack鏈式配置)

yarn add -D webpack-chain || npm install -D webpack-chain

ok! webpack腳手架相關(guān)的依賴我們算是安裝完了,然后我們在工程根目錄底下創(chuàng)建一個webpack配置文件webpack.config.js渐行,用webpack-chain導出一個配置:

const config = new (require("webpack-chain"))();
module.exports = config.toConfig();

然后我們就可以在根目錄執(zhí)行npx webpacknpx webpack-dev-server命令了轰坊,為了方便,我們直接在package.json中聲明兩個腳本builddev,

{
  "name": "webpack-vue-demo",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "build": "rimraf dist && webpack --mode=production",
    "dev": "webpack-dev-server --mode=development --progress"
  },
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "webpack": "^4.44.0",
    "webpack-chain": "^6.5.1",
    "webpack-cli": "^3.3.12",
    "webpack-dev-server": "^3.11.0"
  }
}

我們試著運行一下build命令:

> webpack-vue-demo@1.0.0 build xx/webpack/webpack-vue-demo
> rimraf dist && webpack --mode=production


Insufficient number of arguments or no entry found.
Alternatively, run 'webpack(-cli) --help' for usage info.

Hash: a8dc1c75fbec1af4c624
Version: webpack 4.44.0
Time: 29ms
Built at: 07/27/2020 4:45:12 PM

ERROR in Entry module not found: Error: Can't resolve './src' in 'xxx/webpack/webpack-vue-demo'
npm ERR! code ELIFECYCLE
npm ERR! errno 2
npm ERR! webpack-vue-demo@1.0.0 build: `rimraf dist && webpack --mode=production`
npm ERR! Exit status 2
npm ERR! 
npm ERR! Failed at the webpack-vue-demo@1.0.0 build script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.
?  webpack-vue-demo git:(master) ? 

可以看到祟印,webpack直接報錯了~ ok肴沫! 原因我就不解釋了,沒看過前面文章的童鞋強烈建議先看完再過來實戰(zhàn)蕴忆。

typescript

因為我們需求中需要支持ts颤芬,所以我們繼續(xù)安裝ts相關(guān)依賴:

typescript(ts腳手架)

yarn add -D typescript || npm install -D typescript

ts-loader(ts加載器)

yarn add -D ts-loader || npm install -D ts-loader

ok! ts相關(guān)依賴安裝完畢后,我們可以開始創(chuàng)建我們項目的目錄了套鹅,我們直接在根目錄底下創(chuàng)建一個src目錄站蝠,然后在src目錄下創(chuàng)建一個main.ts空文件當成項目的入口文件:

webpack-vue-demo
    node_modules
    src
        main.ts
    .gitignore
    package.json
    README.md
    webpack.config.js

然后我們?nèi)バ薷囊幌聎ebpack的配置。

入口配置

webpack.config.js:

const path = require("path");
const config = new (require("webpack-chain"))();
config
    .context(path.resolve(__dirname, ".")) //webpack上下文目錄為項目根目錄
    .entry("app") //入口文件名稱為app
        .add("./src/main.ts") //入口文件為./src/main.ts
        .end()
    .output
        .path(path.join(__dirname,"./dist")) //webpack輸出的目錄為根目錄的dist目錄
        .filename( "[name].[contenthash:8].js") //打包出來的bundle名稱為[name].[contenthash:8].js
        .publicPath("./") //publicpath配置為"./"
    .end()

module.exports = config.toConfig();

我們再次執(zhí)行npm run build

?  webpack-vue-demo git:(master) ? npm run build

> webpack-vue-demo@1.0.0 build xxx/webpack/webpack-vue-demo
> rimraf dist && webpack --mode=production

Hash: f102af84da880d301fb5
Version: webpack 4.44.0
Time: 198ms
Built at: 07/27/2020 5:05:26 PM
          Asset       Size  Chunks                         Chunk Names
app.995b67bc.js  964 bytes       0  [emitted] [immutable]  app
Entrypoint app = app.995b67bc.js
[0] multi ./src/main.ts 28 bytes {0} [built]
[1] ./src/main.ts 0 bytes {0} [built]
?  webpack-vue-demo git:(master) ? 

ok卓鹿,這一次我們可以看到菱魔,webpack通過我們配置的入口文件main.ts文件打包出來了一個叫app.995b67bc.js的文件,

dist/app.995b67bc.js:

!function (e) {
    var t = {};

    function n(r) {
        if (t[r]) return t[r].exports;
        var o = t[r] = {i: r, l: !1, exports: {}};
        return e[r].call(o.exports, o, o.exports, n), o.l = !0, o.exports
    }

    n.m = e, n.c = t, n.d = function (e, t, r) {
        n.o(e, t) || Object.defineProperty(e, t, {enumerable: !0, get: r})
    }, n.r = function (e) {
        "undefined" != typeof Symbol && Symbol.toStringTag && Object.defineProperty(e, Symbol.toStringTag, {value: "Module"}), Object.defineProperty(e, "__esModule", {value: !0})
    }, n.t = function (e, t) {
        if (1 & t && (e = n(e)), 8 & t) return e;
        if (4 & t && "object" == typeof e && e && e.__esModule) return e;
        var r = Object.create(null);
        if (n.r(r), Object.defineProperty(r, "default", {
            enumerable: !0,
            value: e
        }), 2 & t && "string" != typeof e) for (var o in e) n.d(r, o, function (t) {
            return e[t]
        }.bind(null, o));
        return r
    }, n.n = function (e) {
        var t = e && e.__esModule ? function () {
            return e.default
        } : function () {
            return e
        };
        return n.d(t, "a", t), t
    }, n.o = function (e, t) {
        return Object.prototype.hasOwnProperty.call(e, t)
    }, n.p = "./", n(n.s = 0)
}([function (e, t, n) {
    e.exports = n(1)
}, function (e, t) {
}]);

哈哈吟孙,估計你是看不懂的澜倦! 因為我們的main.ts是一個空文件,所以打包出來的文件只會包含一些webpack的runtime代碼杰妓。

我們試著去main.ts文件中寫點ts代碼藻治,

src/main.ts:

let a:string="hello";

我們再次運行npm run build

?  webpack-vue-demo git:(master) ? npm run build

...
ERROR in ./src/main.ts 1:5
Module parse failed: Unexpected token (1:5)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
> let a:string="hello";
 @ multi ./src/main.ts app[0]
npm ERR! code ELIFECYCLE
npm ERR! errno 2
npm ERR! webpack-vue-demo@1.0.0 build: `rimraf dist && webpack --mode=production`
npm ERR! Exit status 2
npm ERR! 
npm ERR! Failed at the webpack-vue-demo@1.0.0 build script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.
?  webpack-vue-demo git:(master) ? 

可以看到,webpack直接報錯了巷挥,因為webpack默認的loader只能加載js跟json語法桩卵,不能識別我們的ts語法,所以webpack建議我們配置.ts結(jié)尾文件的loader。

配置ts-loader

webpack.config.js:

const path = require("path");
const config = new (require("webpack-chain"))();
config
    .context(path.resolve(__dirname, ".")) //webpack上下文目錄為項目根目錄
    .entry("app") //入口文件名稱為app
        .add("./src/main.ts") //入口文件為./src/main.ts
        .end()
    .output
        .path(path.join(__dirname,"./dist")) //webpack輸出的目錄為根目錄的dist目錄
        .filename( "[name].[contenthash:8].js") //打包出來的bundle名稱為[name].[contenthash:8].js
        .publicPath("./") //publicpath配置為"./"
        .end()
    .resolve
        .extensions
            .add(".js").add(".jsx").add(".ts").add(".tsx").add(".vue") //配置以.js等結(jié)尾的文件當模塊使用的時候都可以省略后綴
            .end()
        .end()
    .module
        .rule("type-script")
            .test(/\.tsx?$/) //loader加載的條件是ts或tsx后綴的文件
            .use("ts-loader")
                .loader("ts-loader")
                .options({ //ts-loader相關(guān)配置
                    transpileOnly: true,
                    appendTsSuffixTo: ['\\.vue$']
                })
                .end()
            .end()
module.exports = config.toConfig();

然后在根目錄創(chuàng)建一個ts的配置文件tsconfig.json:

{
  "compilerOptions": {
    "target": "esnext",
    "module": "esnext",
    "strict": true,
    "jsx": "preserve",
    "importHelpers": true,
    "moduleResolution": "node",
    "experimentalDecorators": true,
    "esModuleInterop": true,
    "allowSyntheticDefaultImports": true,
    "suppressImplicitAnyIndexErrors": true,
    "resolveJsonModule": true,
    "sourceMap": true,
    "baseUrl": ".",
    "types": [
      "webpack-env"
    ],
    "paths": {
      "@/*": [
        "src/*"
      ]
    },
    "lib": [
      "esnext",
      "dom",
      "dom.iterable",
      "scripthost"
    ]
  },
  "include": [
    "src/**/*.ts",
    "src/**/*.tsx",
    "src/**/*.vue",
  ],
  "exclude": [
    "node_modules"
  ]
}

ok吸占,然后我們再次運行npm run build命令:

?  webpack-vue-demo git:(master) ? npm run build

> webpack-vue-demo@1.0.0 build xxx/webpack-vue-demo
> rimraf dist && webpack --mode=production

Hash: f5bd51439408213acbe2
Version: webpack 4.44.0
Time: 403ms
Built at: 07/27/2020 5:21:40 PM
          Asset       Size  Chunks                         Chunk Names
app.b894f269.js  999 bytes       0  [emitted] [immutable]  app
Entrypoint app = app.b894f269.js
[0] multi ./src/main.ts 28 bytes {0} [built]
[1] ./src/main.ts 47 bytes {0} [built]
?  webpack-vue-demo git:(master) ? 

可以看到晴叨,這次就沒有報錯了凿宾,因為我們的webpack可以通過我們定義的ts-loader識別我們的ts語法了矾屯,我們來驗證一下吧,我們修改main.ts文件:

let a:string="hello";
console.log(a)

代碼很簡單初厚,然后我們執(zhí)行"npm run build"看最后打包出來的文件:

dist/app.b894f269.js

!function (e) {
    var t = {};

   ...
}([function (e, t, n) {
    e.exports = n(1)
}, function (e, t, n) {
    "use strict";
    console.log("hello") //webpack打包過后的代碼
}]);

vue配置

vue

yarn add vue || npm install -S vue

vue-loader(vue加載器)

yarn add -D vue-loader || npm install -D vue-loader

vue-template-compiler(.vue文件模版編譯器)

yarn add -D vue-template-compiler || npm install -D vue-template-compiler

vue-class-component(vue類組件)

yarn add  vue-class-component || npm install -S vue-class-component

vue-property-decorator(vue屬性裝飾器)

yarn add  vue-property-decorator || npm install vue-property-decorator

ok, 然后我們修改一下配置文件件蚕,讓webpack支持.vue文件解析,

webpack.config.js:

const path = require("path");
const config = new (require("webpack-chain"))();
config
    .context(path.resolve(__dirname, ".")) //webpack上下文目錄為項目根目錄
    .entry("app") //入口文件名稱為app
        .add("./src/main.ts") //入口文件為./src/main.ts
        .end()
    .output
        .path(path.join(__dirname,"./dist")) //webpack輸出的目錄為根目錄的dist目錄
        .filename("[name].[hash:8].js")
        .end()
    .resolve
        .extensions
            .add(".js").add(".jsx").add(".ts").add(".tsx").add(".vue") //配置以.js等結(jié)尾的文件當模塊使用的時候都可以省略后綴
            .end()
        .end()
    .module
        .rule("type-script")
            .test(/\.tsx?$/) //loader加載的條件是ts或tsx后綴的文件
            .use("ts-loader")
                .loader("ts-loader")
                .options({ //ts-loader相關(guān)配置
                    transpileOnly: true,
                    appendTsSuffixTo: ['\\.vue$']
                })
                .end()
            .end()
        .rule("vue")
            .test(/\.vue$/)// 匹配.vue文件
                .use("vue-loader")
                .loader("vue-loader")
                .end()
            .end()
        .end()
    .plugin("vue-loader-plugin")//vue-loader必須要添加vue-loader-plugin
        .use(require("vue-loader").VueLoaderPlugin,[])
        .end()
    .devServer
        .host("0.0.0.0") //為了讓外部服務訪問
        .port(8090) //當前端口號
        .hot(true) //熱載
        .open(true) //開啟頁面
module.exports = config.toConfig();

然后我們?nèi)rc目錄下創(chuàng)建一個app.vue文件用來測試产禾,

src/app.vue:

<template>
    <div>{{this.msg}}</div>
</template>

<script lang="ts">
  import {Vue, Component} from "vue-property-decorator";

  @Component
  export default class App extends Vue {
    msg="hello world"
  }
</script>

<style scoped>

</style>

很簡單排作,就是輸出一個"hello world"到頁面,然后我們修改一下“main.ts”文件亚情,

src/main.ts:

import Vue from "vue";
import App from "./app.vue";

new Vue({
  el: "#app",
  render: (h) => h(App)
});

ok! 我們直接運行一下npm run dev:

192:webpack-vue-demo yinqingyang$ npm run dev

> webpack-vue-demo@1.0.0 dev xxx/webpack-vue-demo
> webpack-dev-server --mode=development --progress

10% building 2/2 modules 0 active? ?wds?: Project is running at http://0.0.0.0:8090/
? ?wds?: webpack output is served from /
? ?wds?: Content not from webpack is served from xxx/xxx/webpack-vue-demo
10% building 5/15 modules 10 activexxx/webpack-vue-demo/node_modules/webpack-dev-server/client/utils/createSocketUr? ?wdm?: wait until bundle finished: /
? ?wdm?: Hash: 6b8de437340cfe2ceccd
Version: webpack 4.44.0
Time: 2431ms
Built at: 07/27/2020 8:57:11 PM
          Asset     Size  Chunks                         Chunk Names
app.6b8de437.js  697 KiB     app  [emitted] [immutable]  app
Entrypoint app = app.6b8de437.js
...
[./src/main.ts] 108 bytes {app} [built]
    + 35 hidden modules
? ?wdm?: Compiled successfully.


可以看到妄痪,webpack-dev-server服務已經(jīng)開啟了,并且服務器在8090端口監(jiān)聽楞件,我們直接瀏覽器打開鏈接:http://0.0.0.0:8090/webpack-dev-server

在這里插入圖片描述

webpack-dev-server會把所有生成的文件列在這里衫生,“app.6b8de437.js”就是webpack根據(jù)入口main.ts文件生成的bundle文件。

接下來我們創(chuàng)建一個public目錄土浸,然后在public目錄中創(chuàng)建一個叫index.html的文件用來測試罪针,

public/index.html:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<noscript>your browser should support javascript!</noscript>
<div id="app"></div>
<script src="http://0.0.0.0:8090/app.6b8de437.js"></script>
</body>
</html>

ok,可以看到黄伊,我們直接放了一個div元素供main.ts中的vue實例掛載泪酱,然后就是直接一個script標簽加載入口文件,我們直接把index.html文件在瀏覽器打開:

在這里插入圖片描述

可以看到还最,瀏覽器中顯示了我們的預期結(jié)果墓阀! 但是我們是手動的去引入“app.6b8de437.js”文件的,這難免有點不方便拓轻,所以接下來我們讓它自動導入bundle文件到模版html文件中岂津。

html-webpack-plugin

我們首先安裝html-webpack-plugin:

yarn add -D html-webpack-plugin || npm install -D html-webpack-plugin

然后修改一下配置文件添加html-webpack-plugin插件,

webpack.config.js:

const path = require("path");
const config = new (require("webpack-chain"))();
config
    .context(path.resolve(__dirname, ".")) //webpack上下文目錄為項目根目錄
    .entry("app") //入口文件名稱為app
        .add("./src/main.ts") //入口文件為./src/main.ts
        .end()
    .output
        .path(path.join(__dirname,"./dist")) //webpack輸出的目錄為根目錄的dist目錄
        .filename("[name].[hash:8].js")
        .end()
    .resolve
        .extensions
            .add(".js").add(".jsx").add(".ts").add(".tsx").add(".vue") //配置以.js等結(jié)尾的文件當模塊使用的時候都可以省略后綴
            .end()
        .end()
    .module
        .rule("type-script")
            .test(/\.tsx?$/) //loader加載的條件是ts或tsx后綴的文件
            .use("ts-loader")
                .loader("ts-loader")
                .options({ //ts-loader相關(guān)配置
                    transpileOnly: true,
                    appendTsSuffixTo: ['\\.vue$']
                })
                .end()
            .end()
        .rule("vue")
            .test(/\.vue$/)// 匹配.vue文件
                .use("vue-loader")
                .loader("vue-loader")
                .end()
            .end()
        .end()
    .plugin("vue-loader-plugin")//vue-loader必須要添加vue-loader-plugin
        .use(require("vue-loader").VueLoaderPlugin,[])
        .end()
    .plugin("html")// 添加html-webpack-plugin插件
        .use(require("html-webpack-plugin"),[{
            template: path.resolve(__dirname,"./public/index.html"), //指定模版文件
            chunks:["app"], //指定需要加載的chunk
            inject: "body" //指定script腳本注入的位置為body
        }])
        .end()
    .devServer
        .host("0.0.0.0") //為了讓外部服務訪問
        .port(8090) //當前端口號
        .hot(true) //熱載
        .open(true) //開啟頁面
module.exports = config.toConfig();

ok悦即,然后我們直接npm run dev:

npm run dev

運行后會發(fā)現(xiàn)瀏覽器自動打開了http://0.0.0.0:8090/頁面:

在這里插入圖片描述

雖然是運行成功了吮成,但是ide一直在提示有個地方報錯:

在這里插入圖片描述

意思就是:“導入的app.vue并沒有類型聲明文件”,ok辜梳,我們直接在src目錄底下創(chuàng)建一個shims-vue.d.ts文件用來聲明.vue 文件導出的類型粱甫,

src/shims-vue.d.ts:

declare module "*.vue" {
  import Vue from "vue";
  export default Vue;
}

我們直接聲明了一個module,然后導出一個vue實例,聲明之后就會發(fā)現(xiàn)ide報錯沒有了作瞄。

css樣式(scss)

我們試著在vue模版中使用一下sass語法:

src/app.vue

<template>
    <div class="app-container">{{this.msg}}</div>
</template>

<script lang="ts">
  import {Vue, Component} from "vue-property-decorator";

  @Component
  export default class App extends Vue {
    msg="hello world"
  }
</script>

<style scoped lang="scss">
.app-container{
    color: red;
}
</style>
...
File was processed with these loaders:
 * ./node_modules/vue-loader/lib/index.js
You may need an additional loader to handle the result of these loaders.
| 
| 
> .app-container{
|     color: red;
| }
 @ ./src/app.vue?vue&type=style&index=0&id=5ef48958&scoped=true&lang=scss& 1:0-148 1:164-167 1:169-314 1:169-314
 @ ./src/app.vue
 @ ./src/main.ts
 @ multi ./src/main.ts
? ?wdm?: Failed to compile.

ok, 開啟webpack服務后會發(fā)現(xiàn)報錯了:“找不到能夠解析當前樣式語法的loader”茶宵,那我們接下來就讓webpack支持scss語法。

sass(scss&&sass語法)

yarn add -D sass || npm install -D sass

sass-loader(sass&&scss文件加載器)

yarn add -D sass-loader || npm install -D sass-loader

postcss-loader(css樣式處理工具)

比如:自動添加瀏覽器適配前綴宗挥、壓縮css樣式等等

yarn add -D postcss-loader || npm install -D postcss-loader
cssnano(壓縮css)
yarn add -D cssnano || npm install -D cssnano
autoprefixer(自動添加瀏覽器適配前綴)
yarn add -D autoprefixer || npm install -D autoprefixer

css-loader(css模塊加載器)

yarn add -D css-loader || npm install -D css-loader

mini-css-extract-plugin(抽離css樣式到獨立的.css文件)

yarn add -D mini-css-extract-plugin || npm install -D mini-css-extract-plugin

然后修改配置文件乌庶,webpack.config.js:

const path = require("path");
const config = new (require("webpack-chain"))();
const isDev = process.env.WEBPACK_DEV_SERVER;
config
    .context(path.resolve(__dirname, ".")) //webpack上下文目錄為項目根目錄
    .entry("app") //入口文件名稱為app
        .add("./src/main.ts") //入口文件為./src/main.ts
        .end()
    .output
        .path(path.join(__dirname,"./dist")) //webpack輸出的目錄為根目錄的dist目錄
        .filename("[name].[hash:8].js")
        .end()
    .resolve
        .extensions
            .add(".js").add(".jsx").add(".ts").add(".tsx").add(".vue") //配置以.js等結(jié)尾的文件當模塊使用的時候都可以省略后綴
            .end()
        .end()
    .module
        .rule("type-script")
            .test(/\.tsx?$/) //loader加載的條件是ts或tsx后綴的文件
            .use("ts-loader")
                .loader("ts-loader")
                .options({ //ts-loader相關(guān)配置
                    transpileOnly: true,
                    appendTsSuffixTo: ['\\.vue$']
                })
                .end()
            .end()
        .rule("vue")
            .test(/\.vue$/)// 匹配.vue文件
                .use("vue-loader")
                .loader("vue-loader")
                .end()
            .end()
        .rule("sass")
            .test( /\.(sass|scss)$/)//sass和scss文件
            .use("extract-loader")//提取css樣式到單獨css文件
                .loader(require('mini-css-extract-plugin').loader)
                .options({
                    hmr: isDev //開發(fā)環(huán)境開啟熱載
                })
                .end()
            .use("css-loader")//加載css模塊
                .loader("css-loader")
                .end()
            .use("postcss-loader")//處理css樣式
                .loader("postcss-loader")
                .options( {
                    config: {
                       path: path.resolve(__dirname, "./postcss.config.js")
                    }
                })
                .end()
            .use("sass-loader")//sass語法轉(zhuǎn)css語法
                .loader("sass-loader")
                .end()
            .end()
        .end()
    .plugin("vue-loader-plugin")//vue-loader必須要添加vue-loader-plugin
        .use(require("vue-loader").VueLoaderPlugin,[])
        .end()
    .plugin("html")// 添加html-webpack-plugin插件
        .use(require("html-webpack-plugin"),[{
            template: path.resolve(__dirname,"./public/index.html"), //指定模版文件
            chunks:["app"], //指定需要加載的chunk
            inject: "body" //指定script腳本注入的位置為body
        }])
        .end()
    .plugin("extract-css")//提取css樣式到單獨css文件
        .use(require('mini-css-extract-plugin'), [{
            filename: "css/[name].css",
            chunkFilename: "css/[name].css"
        }])
        .end()
    .devServer
        .host("0.0.0.0") //為了讓外部服務訪問
        .port(8090) //當前端口號
        .hot(true) //熱載
        .open(true) //開啟頁面
module.exports = config.toConfig();

然后我們給postcss指定配置文件种蝶,我們在根目錄創(chuàng)建一個postcss.config.js:

module.exports = {
    plugins: [
        require("autoprefixer")(),
        require("cssnano")({
            preset: ['default', {
                mergeLonghand: false,
                cssDeclarationSorter: false
            }]
        })
    ]
};

可以看到,我們加入了“autoprefixer”跟“cssnano”插件用于自動添加瀏覽器前綴跟css壓縮瞒大,然后我們在根目錄創(chuàng)建一個.browserslistrc用于當前項目瀏覽器列表螃征,

.browserslistrc:

> 0.25%, not dead

css樣式相關(guān)的配置我這里就不詳細說明了,不懂的小伙伴可以看前面的文章透敌,配置完css后我們再看一下我們的app.vue文件盯滚,

src/app.vue:

<template>
    <div class="app-container">{{this.msg}}</div>
</template>

<script lang="ts">
  import {Vue, Component} from "vue-property-decorator";

  @Component
  export default class App extends Vue {
    msg="hello world"
  }
</script>

<style scoped lang="scss">
.app-container{
    color: green;
}
</style>

??,可以看到酗电,我們給了當前div一個樣式:

.app-container{
    color: green;
}

然后我們運行npm run dev指令:

npm run dev
在這里插入圖片描述

ok, 然后我們修改成為紅色試試魄藕,src/app.vue:

<template>
    <div class="app-container">{{this.msg}}</div>
</template>

<script lang="ts">
  import {Vue, Component} from "vue-property-decorator";

  @Component
  export default class App extends Vue {
    msg="hello world"
  }
</script>

<style scoped lang="scss">
.app-container{
    color: red;
}
</style>
在這里插入圖片描述

可以看到,當我們修改了樣式后撵术,mini-css-extract-plugin觸發(fā)了熱載背率,頁面樣式自動更新。

ok! 這一節(jié)先到這里了嫩与,因為扛不住了要睡覺了??~ 下節(jié)繼續(xù)~敬請期待G拮恕!蕴纳!

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末会油,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子古毛,更是在濱河造成了極大的恐慌翻翩,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,743評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件稻薇,死亡現(xiàn)場離奇詭異嫂冻,居然都是意外死亡,警方通過查閱死者的電腦和手機塞椎,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,296評論 3 385
  • 文/潘曉璐 我一進店門桨仿,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人案狠,你說我怎么就攤上這事服傍。” “怎么了骂铁?”我有些...
    開封第一講書人閱讀 157,285評論 0 348
  • 文/不壞的土叔 我叫張陵吹零,是天一觀的道長。 經(jīng)常有香客問我拉庵,道長灿椅,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,485評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮茫蛹,結(jié)果婚禮上操刀,老公的妹妹穿的比我還像新娘。我一直安慰自己婴洼,他們只是感情好骨坑,可當我...
    茶點故事閱讀 65,581評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著窃蹋,像睡著了一般卡啰。 火紅的嫁衣襯著肌膚如雪静稻。 梳的紋絲不亂的頭發(fā)上警没,一...
    開封第一講書人閱讀 49,821評論 1 290
  • 那天,我揣著相機與錄音振湾,去河邊找鬼杀迹。 笑死,一個胖子當著我的面吹牛押搪,可吹牛的內(nèi)容都是我干的树酪。 我是一名探鬼主播,決...
    沈念sama閱讀 38,960評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼大州,長吁一口氣:“原來是場噩夢啊……” “哼续语!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起厦画,我...
    開封第一講書人閱讀 37,719評論 0 266
  • 序言:老撾萬榮一對情侶失蹤疮茄,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后根暑,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體力试,經(jīng)...
    沈念sama閱讀 44,186評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,516評論 2 327
  • 正文 我和宋清朗相戀三年排嫌,在試婚紗的時候發(fā)現(xiàn)自己被綠了畸裳。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,650評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡淳地,死狀恐怖怖糊,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情颇象,我是刑警寧澤伍伤,帶...
    沈念sama閱讀 34,329評論 4 330
  • 正文 年R本政府宣布,位于F島的核電站夯到,受9級特大地震影響嚷缭,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,936評論 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧姨涡,春花似錦赡若、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,757評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至砰识,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間佣渴,已是汗流浹背辫狼。 一陣腳步聲響...
    開封第一講書人閱讀 31,991評論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留辛润,地道東北人膨处。 一個月前我還...
    沈念sama閱讀 46,370評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像砂竖,于是被迫代替她去往敵國和親真椿。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 43,527評論 2 349