webpack的入門實踐,看這篇就夠了

webpack的入門實踐

我會將所有的讀者概括為初學者,即使你可能有基礎,學習本節之前我希望你具有一定的JavaScript和node基礎

  • 文中的 ... ...代表省略掉部分代碼,和上面的代碼相同
  • 文中的文件夾如果沒有說創建,並且項目默認沒有的是需要你手動增加的
  • 不會特別細緻,但是足夠入門

資源

  • 視頻教程
  • 我的個人博客

什麼是webpack

Web瀏覽器使用HTML,CSS和JavaScript。隨着項目的發展,跟蹤和配置所有這些文件變得非常複雜,解決這個問題就需要一個新的工具

類似webpack的工具還有Grunt和Gulp,webpack是模塊管理工具,把你的項目按照你的想法進行劃分模塊打包,舉個最簡單的例子,這個頁面需要加載一個 a.js和b.js,但是你只想加載一個js文件,就可以使用webpack將兩個文件進行合併,當然webpack的功能不止於此,代碼轉化、項目優化、代碼分割、代碼預編譯、自動構建、自動刷新…

再比如你想你的代碼兼容其他老的瀏覽器,你的css代碼兼容不同的瀏覽器內核,或者你想自動精簡掉你寫了但是沒有用到的代碼,這些都可以使用webpack實現

如果你是vue或者react等框架的使用者,肯定使用過 vue-cli 或 react-create-app 這類腳手架工具,那麼實現這個效果,就要學習webpack

快速入門

注意本文都是webpack4的內容

安裝

創建一個 webpackdemo文件夾,使用命令npm init -y快速初始化一個項目

安裝 webpack可以使用全局安裝

npm install webpack -g

但是我更推薦你在每個項目裏面單獨引入,這樣可以控製版本,如果你使用 webpack 4+ 版本,你還需要安裝 CLI。

npm install -D webpack@<version>
npm install -D webpack-cli

本文默認使用項目引入的方式,我們在根目錄下新建 src/index.js,webpack在不進行任何配置的情況下,會默認尋找這個文件

然後命令行執行node_modules\.bin\webpack,如果你是全局安裝的可以直接使用webpack命令

注意此時命令行爆黃色警告,這是沒有指定當前模式的原因,並且可以發現,目錄下多了一個 dist/main.js文件,這便是默認的輸出文件

為了體驗項目的打包,我們新建一個src/clg.js文件

export default function clg(msg) {
    console.log(msg);
}

我們在index.js裏面導入並使用

import clg from './clg';
clg('webpack init');

然後根目錄我們新建一個 index.html文件,引入打包后的文件

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="./dist/main.js"></script>
</head>
<body>
</body>
</html>

然後修改一下打包命令,指定當前為開發模式,再次運行.\node_modules\.bin\webpack --mode development

這次打包沒有爆警告,並且我們打開index.html控制台查看結果

webpack.config.js配置文件

在前面,我們都是使用webpack-cli為我們提供的默認配置,如果我們想使用webpack更強大的功能還是需要自定義配置文件的,在根目錄新建webpack.config.js,執行webpack命令的時候會自動找到它

const path = require('path');

module.exports = {
    // 環境
    mode: 'development',
    // 目標文件
    entry: [path.resolve(__dirname, './src/index.js')],
    // 自定義輸出文件
    output: {
        path: path.resolve(__dirname, './dist'), //路徑
        filename: 'main.js' //文件名稱
    },
    // 插件
    plugins: [

    ],
    // 給導入的文件制定規則
    module: {

    }
}

為了方便調試,我們在 package.json中添加命令,此時執行命令npm run dev或npm run build就非常方便了

注意 scripts命令裏面可省略 .\node_modules\.bin\使用 npx webpack也是這個效果

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

多個目標和輸出文件

在上面是一個目標文件index.js和一個輸出文件main.js,如果我們想要對多個目標文件進行打包,且輸出多個文件該怎麼辦呢?我們在根目錄新建一個 other.js

首先我們將entry修改為多個目標文件,並設置一個鍵名,然後修改輸出文件的名稱為變量[name]

const path = require('path');
module.exports = {
    // 環境
   mode: 'development',
    // 目標文件
   entry: {
        index: path.resolve(__dirname, './src/index.js'),
        other: path.resolve(__dirname, './src/other.js')
    },
    // [path.resolve(__dirname, './src/index.js'), path.resolve(__dirname, './src/other.js')],
    // 自定義輸出文件
    output: {
        path: path.resolve(__dirname, './dist'), //路徑
        filename: '[name].bundle.js' //文件名稱
    },
}

此時我們執行 npm run build可發現dist目錄的多個js文件

使用插件來測試程序

在上面,我們自己創建了一個 index.html文件來測試我們打包的文件是否正常,其實webpack為我們提供了更為自動的方式,在這裏我們將使用第一個webpcak插件html-webpack-plugin,首先需要安裝它

npm i html-webpack-plugin -D

然後我們在 webpack.config.js中配置使用這個插件

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
    // 目標文件
    entry: {
        index: path.resolve(__dirname, './src/index.js'),
        other: path.resolve(__dirname, './src/other.js'),
    },
    // 自定義輸出文件
    output: {
        path: path.resolve(__dirname, './dist'), //路徑
        filename: 'main.js' //文件名稱
    },
    // 插件
    plugins: [
        new HtmlWebpackPlugin({
            title: "Webpack init",
        }),
    ],
}

此時,我們刪除 index.html文件,然後再次執行npm run build可以發現,webpack自動為我們創建了一個indedx.html文件,並引入了打包后的js文件

多個頁面

在上面,我們都是使用的一個 index.html單頁面,實際開發中漸進式的單頁面程序也比較多,但是還是會有多頁面的場景

簡單的修改一下webpack.config.js,多次實例化插件就可以了,filename為輸出文件名,chunks為這個頁面需要使用的js文件,當然如果你不是使用的自動生成頁面,可以使用template屬性指定你的頁面位置

module.exports = {
    ... ... 
    // 插件
    plugins: [
        new HtmlWebpackPlugin({
            filename:"index.html",
            title: "Webpack init",
            chunks:['index']
        }),
        new HtmlWebpackPlugin({
            filename:"other.html",
            title: "Webpack init",
            chunks:['other']
        }),
        new webpack.NamedModulesPlugin(),
        new webpack.HotModuleReplacementPlugin(),
        new CleanWebpackPlugin(),
    ],
    ... ...
}

此時我們使用npm run dev,此時可以發現dist目錄輸出了兩個頁面並引入不同的js文件

source map

打包后的js文件都混淆到了一個或者多個文件中,丟失了原本的文件格式,如果在運行過程中出現bug,很難定位原本的錯誤位置 source map 就可以解決這個問題

為了更容易地追蹤錯誤和警告,JavaScript 提供了 source map 功能,將編譯后的代碼映射回原始源代碼。如果一個錯誤來自於 b.js,source map 就會明確的告訴你。

開啟 source map 非常簡單,只需要在配置文件webpack.config.js中增加

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const webpack = require('webpack');
module.exports = {
	... ...
    devtool: "cheap-module-eval-source-map",
 	... ...
}

為了驗證是否生效,我們在other.js中增加

console.log('other');
console.error("error")

然後使用npm run dev,接着在控制台查看錯誤並點擊,便能跳轉到出錯的位置

devtool有多個模式,不同的性能和品質,開發環境中我們希望性能更好,生產環境我們希望質量更好詳細配置

開發環境可以使用cheap-module-eval-source-map、eval 、eval-source-map

生產環境可以使用inline-source-map、inline-cheap-module-source-map、cheap-source-map

觀察模式和webpack-dev-server

在上面的內容中,每次修改內容后都需要手動執行構建命令,webpack為我們提供了更為自動的方法

觀察模式

我們只需簡單的修改一下命令npm run dev --watch,同樣的我們為了方便,可以直接將命令寫入 package.json中

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

此時,我們執行npm run watch命令后,只要修改文件中的內容,webpack即可自動構建

webpack-dev-server

但是在實際開發中,使用webpack-dev-server(簡稱wds)更為方便,它為我們提供了一個簡單的服務器,並且瀏覽器能夠實時加載,也就是說,當你修改文件保存后,瀏覽器可自動加載最新的內容,並且這一切都是發生在內存中,構建速度更快

安裝

npm i webpack-dev-server -D

同樣的我們在 package.json中添加一個命令

"scripts": {
  "test": "echo \"Error: no test specified\" && exit 1",
  "dev": "webpack --mode development",
  "build": "webpack --mode production",
  "watch": "webpack --mode production --watch",
  "server": "webpack-dev-server --mode development"
},

此時,我們只需執行npm run server,webpack便可自動創建一個服務器,並將項目運行在其中,當我們修改文件中的任意內容的時候,頁面便會自動刷新

如果使用過 vscode的插件live server的同學,不難發現,這就是類似的功能

我們還可以在 webpack.config.js中進一步的對 wds進行配置

module.exports = {
	... ...
    devServer: {
     /**
      * 日誌模式  friendly-errors-webpack-plugin 插件可以優化輸出
      * errors-only  只在發生錯誤時觸發
      * minimal 只在發生錯誤或者有新的編譯時輸出
      * none 沒有輸出
      * normal 標準輸出
      * verbose 全部輸出
      */
     stats: "errors-only",
     //默認地址 localhost
     host: process.env.HOST,
     //默認端口 8080
     port: process.env.PORT,
     //是否直接打開瀏覽器
     open: true,
 },
   ... ...
}

此時我們再次運行 npm run server,webpack便能按照我們的配置來構建了

HMR

模塊熱替換(Hot Module Replacement 或 HMR)是 webpack 提供的最有用的功能之一。它允許在運行時更新各種模塊,而無需進行完全刷新。

在上面的內容中,我們修改文件的部分內容,webpack都需要將項目重新構建並通知瀏覽器重新渲染,這個過程十分浪費資源,使用 HMR就可以實現,修改哪裡,重新加載哪裡的這個效果

NamedModulesPlugin插件是在熱加載時直接返回更新文件名

使用 HMR我們只需要簡單的配置即可

webpack.config.js

... ... 
const webpack = require('webpack');
module.exports = {
	... ...
    // 插件
    plugins: [
      	... ...
        new webpack.NamedModulesPlugin(),
        new webpack.HotModuleReplacementPlugin()
    ],
    devServer: {
		... ...
        //是否開啟熱更替
        hot: true
    },
}

為了驗證是否是局部更替,我么修改一下文件內容

index.js

import clg from './clg';
console.log('webpack init');

// module.hot Webpack通過全局變量公開HMR接口
if (module.hot) {
    module.hot.accept('./clg.js', function () {
        clg('檢測到clg模塊修改');
    })
}

此時我們使用 npm run server 將項目運行起來,簡單的修改 index.js文件中內容,發現控制台只打印了

我們再次修改clg.js中內容,打個空格再保存即可,此時驗證了我們想要的效果

生產環境和開發環境分離

開發環境(development)和生產環境(production)的構建目標差異很大,官方建議為每個環境編寫彼此獨立的 webpack 配置。

我們將新建兩個配置文件webpack.dev.js(開發環境)和webpack.prod.js(生產環境)但是它們具有很多相同的配置,所以我們再新建一個webpack.common.js(通用配置)文件

我們使用webpack-merge插件來將不同的環境配置文件和通用配置文件進行合併,並且使用clean-webpack-plugin插件來每次重置我們的構建文件夾

npm i webpack-merge -D
npm i clean-webpack-plugin -D

webpack.common.js

const path = require('path');
const webpack = require('webpack');
const {
    CleanWebpackPlugin
} = require("clean-webpack-plugin");
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
    entry: [path.resolve(__dirname, './src/index.js')],
    plugins: [
        new CleanWebpackPlugin(),
        new webpack.NamedModulesPlugin(),
        new HtmlWebpackPlugin({
            title: 'Webpack init'
        })
    ],
    output: {
        filename: 'main.js',
        path: path.resolve(__dirname, 'dist')
    },
    module: {
        rules: [
            
        ]
    }
};

webpack.dev.js

我們再開發環境配置文件中配置 server的相關信息,並且打開source-map

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

module.exports = merge(common, {
    mode:"development",
    devtool: 'eval',
    devServer: {
        stats: "errors-only",
        //默認地址 localhost
        host: process.env.HOST,
        //默認端口 8080
        port: process.env.PORT,
        //是否直接打開瀏覽器
        open: true,
        //是否開啟熱更替
        hot: true,
    },
    module: {
        rules: [
            //打包css文件的規則
            {
                test: /\.css$/,
                use: ['style-loader', 'css-loader']
            }
        ]
    }
});

webpack.prod.js

我們在生產環境配置文件中省略掉其他配置文件

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

module.exports = merge(common, {
  mode: "production",
    
});

然後我們在 package.json增加一些命令

"envdev":"webpack-dev-server --config webpack.dev.js",
"envbuild":"webpack --config webpack.prod.js"

此時,我們的項目構建就更加清晰了

管理資源文件

webpack不僅僅是打包 js文件這麼簡單,此處我們簡單的介紹幾個常用的資源打包方式,更詳細的內容可以參考官方文檔

管理css

使用過腳手架的同學應該都記得,項目裏面的css文件可以通過js直接引入的方式使用

import 'xxx.css';

來簡單實踐一下,首先安裝插件

npm i  style-loader css-loader -D

為了展示我們的打包效果,我們新建一個 js/divdoc.js文件用來在頁面中渲染出一個字符串(此時我們已將clg.js也轉移到 ./js 文件夾)

export default function divdoc() {
    //創建一個dom
    let element = document.createElement('div');
    element.innerHTML = "webpack init";
    element.classList.add('init');
    //將dom渲染到頁面上
    document.body.appendChild(element);
}

在index.js中導入並使用

import clg from './js/clg';
import divdoc from './js/divdoc';
console.log('webpack init now');

divdoc();

// module.hot Webpack通過全局變量公開HMR接口
if (module.hot) {
    module.hot.accept('./js/clg.js', function () {
        clg('檢測到clg模塊修改');
    })
}

此時運行 npm run server查看效果

接下來我們新建 src/css/app.css文件

我們前面渲染的dom節點是包含一個 class名為 init的

.init{
    color: red;
}

編寫規則webpack.dev.js

module.exports = {
	... ...
    // 給導入的文件制定規則
    module: {
        rules: [
            //打包css文件的規則
            {
                test: /\.css$/,
                use: ['style-loader', 'css-loader']
            },
        ]
    }
}

在index.js中導入,並查看效果

import  './css/app.css';

順便可以打包一下less,首先安裝插件npm i -D less-loader,然後寫一下規則

module: {
    rules: [
        //打包css文件的規則
        {
            test: /\.css$/,
            use: ['style-loader', 'css-loader']
        },
        {
            test: /\.less$/,
            use: ['style-loader', 'css-loader', 'less-loader']
        },
    ]
}

我們新建一個 src/css/app.less文件

.init{
    color: red;
}

我們在 index.js中註釋掉原本導入的 app.css,然後導入less文件

import './css/app.less';

重新構建項目,查看項目,效果依然生效,同理sass、stylus也是這個用法,這裏不再贅述

分離css

在前面,我們打包css,最終都是將css代碼添加到頁面的 style標籤中,如果我們想將所有的css都打包到專門的文件裏面可以使用mini-css-extract-plugin插件

npm i mini-css-extract-plugin -D

然後修改一下配置webpack.prod.js

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

module.exports = {
  	... ...
    // 插件
    plugins: [
        new MiniCssExtractPlugin({
            filename: "styles/[name].css",
        })
    ],
    // 給導入的文件制定規則
    module: {
        rules: [
            //打包css文件的規則
            // {
            //     test: /\.css$/,
            //     use: ['style-loader', 'css-loader']
            // },
            {
                test: /\.css$/i,
                use: [
                    MiniCssExtractPlugin.loader, 'css-loader'
                ],
            }
        ]
    }
    ... ...
}

此時我們執行npm run build可以發現dist目錄下面創建了一個index.css文件,因為我們是在 index.js中導入css文件的,[name]的值是js的文件名,而不是css的名

當然如果你想指定輸入和導出的css的名字也是可以的,使用這種方式,你就不需要在js中再次引入css文件了

entry: {
    index: path.resolve(__dirname, './src/index.js'),
    other: path.resolve(__dirname, './src/other.js'),
    app: path.resolve(__dirname, './src/css/app.css')
},

webpack在處理樣式方面還有很多很強大的插件,比如purgecss可以精簡掉頁面中沒有使用的css樣式、Autoprefixer可以自動給你添加不同瀏覽器兼容的css插件

管理圖片和字體

在網頁中,圖片一般都是加載的網路路徑,但是在開發中我們都是使用的本地圖片,那麼為了保證上線后和本地的資源位置保持一致,我們可以使用webpack來進行一下打包,最後統一上傳oss存儲

首先需要安裝url-loader

npm i url-loader -D

然後我們在 webpack.common.js中進行配置

const path = require('path');
const webpack = require('webpack');

const {
    CleanWebpackPlugin
} = require("clean-webpack-plugin");
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
    entry: [path.join(__dirname, './src/index.js')],
    plugins: [
        new CleanWebpackPlugin(),
        new webpack.NamedModulesPlugin(),
        new HtmlWebpackPlugin({
            title: 'Webpack init'
        })
    ],
    output: {
        filename: 'main.js',
        path: path.resolve(__dirname, 'dist'),
        //靜態文件打包的網絡路徑
        publicPath:'https://www.lookroot.cn/assets/'
    },
    module: {
        rules: [
            {
                test: /\.(png|svg|jpg|gif)$/,
                use: {
                    loader: 'url-loader',
                    options: {
                        //超過這個大小,圖片就打包為圖片,不超過就打包為base64格式的代碼
                        limit: 1000,
                        //打包文件名
                        name: "img/[hash].[ext]",
                    },
                }
            },
        ]
    }
};

為了驗證,首先我們放一張圖片logo.jpg到src/asserts/img目錄下,我們簡單的修改一下app.css

.init {
  color: red;

}
body {
  background-image: url("../assets/img/logo.jpg");
  background-repeat: no-repeat;
}

同樣的我們也可以在js代碼里使用圖片,修改一下divdoc.js

import logo from "../assets/img/logo.jpg";
export default function divdoc() {
	... ...
    // 插入一張圖片
    let img = document.createElement('img');
    img.src = logo;
    element.appendChild(img);
   ... ...
}

然後使用npm run envdev運行起來,效果是正常的

然後我們使用npm run envbuild執行編譯,然後我們打開dist/img/main.css

body {
  background-image: url(https://www.lookroot.cn/assets/img/494654d849ba012e2aab0505d7c82dc0.jpg);
  background-repeat: no-repeat;
}

我們可以發現,webpack就給我們自動加上了網絡路徑,對於圖片的處理,還有可以優化圖片的[image-webpack-loader(https://github.com/tcoopman/image-webpack-loader)、可以自動生成雪碧圖的postcss-sprites

除了上面我說的這些資源外,webpack還支持非常多的資源格式,只要理解這個思想,使用也不難

代碼檢查和代碼轉換

Eslint代碼檢查

eslint是實際開發中非常常用的代碼檢查工具,我們在webpack中使用它來進行代碼檢查

首先安裝eslint、loader、錯誤格式化插件

npm i eslint  eslint-loader eslint-friendly-formatter -D

然後我們在根目錄新建一個.eslintrc.json,當然你也可以使用命令npx eslint --init來初始化配置文件

rules代表規則,這裏我設置一個禁止使用 alert代碼來測試是否可以完成代碼檢查,更多規則請看文檔

{
    "env": {
        "browser": true,
        "es6": true,
        "node": true
    },
    "extends": "eslint:recommended",
    "parserOptions": {
        "ecmaVersion": 11,
        "sourceType": "module"
    },
    "rules": {
        "no-alert": 2
    }
}

然後在webpack.dev.js中增加配置

 module: {
     rules: [
        ... ... 
         {
             test: /\.js$/,
             loader: 'eslint-loader',
             enforce: 'pre',
             include: [path.resolve(__dirname, 'src')],
             options: {
                 formatter: require('eslint-friendly-formatter')
             }
         }
     ]
 }

然後我們在 index.js文件中增加一句alert("webpack init"),然後使用命令npm run envdev發現報錯,eslint成功捕捉到了錯誤

同樣的你還可以使用 StyleLint工具來檢查你的css代碼

babel代碼轉化

在實際開發中如果使用了 es6+的代碼,有些瀏覽器是不支持的,為了兼容,所有需要將代碼進一步轉化,可以使用babel進行轉化

babel的使用稍微比較繁瑣,本文只介紹在webpack的使用方法,更多細緻的東西請自行查閱

安裝本體和loader babel-loader @babel/core, @babel/preset-env是轉換插件的預設組合,@babel/plugin-transform-runtime用來解決一些瀏覽器不支持的方法和對象問題

npm i @babel/runtime -S
npm i  babel-loader  @babel/core @babel/preset-env @babel/plugin-transform-runtime -D

然後我們在根目錄新建一個配置文件.babelrc,使用@babel/preset-env提供的插件集合能完成大部分的工作了,targets表示我們的代碼要運行到哪些平台上面,更為詳細的請點擊

{
    "presets": [
        [
            "@babel/preset-env",
            {
                "useBuiltIns": "usage",
                "corejs": 3,
                "targets": {
                  	"browsers": [ "ie >= 8", "chrome >= 62" ]
                }
            }
        ]
    ]
}

然後修改一下webpack.dev.js

module: {
    rules: [
       ... ... 
        {
            test: /\.js$/,
            use: [{
                loader: 'babel-loader',
            }]
        }
    ]
}

為了驗證代碼是否轉換成功,我們在index.js中添加代碼

const say=(msg)=>{
    console.log(msg);
}

然後使用命令npm run envdev,並打開source map 查看源文件,可以發現箭頭函數已經被轉換了

本節的內容就是這些,下一次將會有個簡單的實戰,對於webpack還有很多要學習的地方,比如打包優化、插件編寫等等學完基礎以後,這些就需要你自己去探索

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

※網頁設計公司推薦不同的風格,搶佔消費者視覺第一線

※Google地圖已可更新顯示潭子電動車充電站設置地點!!

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※別再煩惱如何寫文案,掌握八大原則!

接口調用超時的實現原理

  平常開發過程中,如果涉及到RPC調用,對於服務調用方和服務提供方,都是可以設置接口超時時間的。以調用方為例,調用方需要調用遠程的一個接口,為了保證服務的質量,一般會設置調用接口的超時時間,比如將調用接口的超時時間設置為1秒,當調用遠程接口后,經過1秒還未拿到結果,那麼就認為是超時了,調用方就不會繼續等待服務提供方返回結果,而是直接拋出一個SocketTimeOutException。

  其實不僅僅是RPC接口調用需要設置超時時間,數據庫、緩存這些一樣的,一般都會設置超時時間,不能讓程序無休止的等待下去。

  那麼問題來了!!應用或者說框架,是如何設置超時時間的呢?我們設置超時時間為1秒,那麼程序是怎麼保證1秒后就停止調用了呢?這也就是本文要介紹的,接口調用設置超時時間的原理。

  本文將以設置調用數據庫超時為例,介紹設置超時時間是怎麼實現的,明白這個原理后,其他比如RPC調用、緩存調用的超時原理也就明白。

 

CallUtils-帶有超時的執行工具類

  下面是一個CallUtils,包含一個線程池和execute方法,execute方法中默認超時時間為1秒。

package cn.ganlixin.util;
import java.util.concurrent.*;

/**
 * 帶有超時的任務執行器
 */
public class CallUtils {

    /**
     * 用於執行任務的線程池
     */
    private static ExecutorService executorService = Executors.newFixedThreadPool(5);

    /**
     * 執行任務,並且超時時間為1秒
     *
     * @param callable 需要執行的任務
     * @param <T>      任務執行完畢后返回值類型
     * @return 任務結果
     */
    public static <T> T execute(Callable<T> callable) {

        // 提交任務
        Future<T> future = executorService.submit(callable);

        try {
            return future.get(1, TimeUnit.SECONDS);
        } catch (InterruptedException | ExecutionException | TimeoutException e) {
            e.printStackTrace();
        }

        return null;
    }
}

  

UserService-將調用數據庫

  UserService使用CallUtils來執行數據庫操作,因為CallUtils設置有調用超時:

package cn.ganlixin.service;

import cn.ganlixin.dao.UserDAO;
import cn.ganlixin.model.User;
import cn.ganlixin.util.CallUtils;

import java.util.List;

public class UserService {

    private UserDAO userDAO = new UserDAO();

    public List<User> getAllUser() {
        return CallUtils.execute(() -> userDAO.getAllUserFromDB());
    }
}

  

UserDAO-耗時的數據庫操作

  userDAO中,作為測試,只提供了一個getAllUserFromDB方法,休眠2秒來模擬數據庫操作,因為UserService使用CallUtils來調用該方法,CallUtils的超時時間為1秒,所以該數據庫操作必定會超時:

package cn.ganlixin.dao;
import cn.ganlixin.model.User;
import java.util.List;
import java.util.concurrent.TimeUnit;

public class UserDAO {

    /**
     * 從DB獲取全量user列表
     */
    public List<User> getAllUserFromDB() {
        try {
            // 模擬數據庫操作,耗時2秒
            TimeUnit.SECONDS.sleep(2);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        return null;
    }
}

  

進行測試

  創建測試類,測試UserService的getAllUser方法,因為getAllUser方法中使用CallUtils來調用數據庫操作,CallUtils的超時時間為1秒,而數據庫操作需要2秒,所以getAllUser方法必然會超時。

package cn.ganlixin.test;
import cn.ganlixin.service.UserService;
import org.junit.Test;

public class TestUserService {

    public UserService userService = new UserService();

    @Test
    public void testGetAllUser() {
        userService.getAllUser();
    }
}

  執行測試,輸出如下:

  

 

 

總結

  本文演示了接口超時調用的原理,實現接口調用超時,無非是通過將任務提交到線程池后,使用future.get,設置超時時間即可。

  上面的代碼很多細節都不太規範,比如涉及到數據庫的超時,應該是數據庫連接池的超時配置,而我在演示時是直接使用CallUtils來替代了,但是明白這個原理就OK。

 

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※網頁設計公司推薦不同的風格,搶佔消費者視覺第一線

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

※南投搬家前需注意的眉眉角角,別等搬了再說!

※新北清潔公司,居家、辦公、裝潢細清專業服務

IDEA版本彩虹屁插件idea-rainbow-fart,一個在你編程時瘋狂稱讚你的 IDEA擴展插件

緣起

是否聽說過程序員鼓勵師,不久前出了一款vscode的插件rainbow-fart,可以在寫代碼的時候,匹配到特定關鍵詞就瘋狂的拍你馬屁。

vscode的下載嘗試過,但是作為日常將IDEA作為主力生產工具的同學來說,如何體驗呢? 於是假期花了一點時間,寫了一個idea版本的插件idea-rainbow-fart。

使用說明

默認使用中文語音包,可以在setting里設置

打開設置:

選擇第三方語音包:

可以到 https://github.com/topics/vscode-rainbow-fart 查找語音包。

點擊確定生效:

原理

沒啥原理,就是一款簡單的idea插件,對沒寫過插件的我來說,需要先看下官方文檔,基本上看下面這一篇就OK:

https://www.jetbrains.org/intellij/sdk/docs/basics/getting_started.html

讀取語音包

先來看下語音包的設計:


{
  "name": "KugimiyaRie",
  "display-name": "KugimiyaRie 釘宮理惠 (Japanese)",
  "avatar": "louise.png",
  "avatar-dark": "shana.png",
  "version": "0.0.1",
  "description": "傲嬌釘宮,鞭寫鞭罵",
  "languages": [
    "javascript"
  ],
  "author": "zthxxx",
  "gender": "female",
  "locale": "jp",
  "contributes": [
    {
      "keywords": [
        "function",
        "=>"
      ],
      "voices": [
        "function_01.mp3",
        "function_02.mp3",
        "function_03.mp3"
      ]
    },
	...
	]
}

對Java來說,定義兩個bean類,解析json即可:

/**
     * 加載配置
     */
    public static void loadConfig() {
        try {
            //
            FartSettings settings = FartSettings.getInstance();
            if (!settings.isEnable()) {
                return;
            }
            String json = readVoicePackageJson("manifest.json");
            Gson gson = new Gson();
            Manifest manifest = gson.fromJson(json, Manifest.class);
            // load contributes.json
            if (manifest.getContributes() == null) {
                String contributesText = readVoicePackageJson("contributes.json");
                Manifest contributes = gson.fromJson(contributesText, Manifest.class);
                if (contributes.getContributes() != null) {
                    manifest.setContributes(contributes.getContributes());
                }
            }
            Context.init(manifest);

        } catch (IOException e) {
        }
    }

監控用戶輸入

自定義一個Handler類繼承TypedActionHandlerBase即可,需要實現的方法原型是:

public void execute(@NotNull Editor editor, char charTyped, @NotNull DataContext dataContext)

chartTyped就是輸入的字符,我們可以簡單粗暴的將這些組合到一起即可,用一個list緩存,然後將拼接后的字符串匹配關鍵詞。

     private List<String> candidates = new ArrayList<>();

    @Override
    public void execute(@NotNull Editor editor, char charTyped, @NotNull DataContext dataContext) {
        candidates.add(String.valueOf(charTyped));
        String str = StringUtils.join(candidates, "");
        try {
            List<String> voices = Context.getCandidate(str);
            if (!voices.isEmpty()) {
                Context.play(voices);
                candidates.clear();
            }
        }catch (Exception e){
            // TODO
            candidates.clear();
        }

        if (this.myOriginalHandler != null) {
            this.myOriginalHandler.execute(editor, charTyped, dataContext);
        }
    }

匹配關鍵詞更簡單,將讀取出來的json,放到hashmap中,然後遍歷map,如果包含關鍵詞就作為語音候選:

    public static List<String> getCandidate(String inputHistory) {


        final List<String> candidate = new ArrayList<>();

        FartSettings settings = FartSettings.getInstance();
        if (!settings.isEnable()) {
            return candidate;
        }
        if (keyword2Voices != null) {
            keyword2Voices.forEach((keyword, voices) -> {
                if (inputHistory.contains(keyword)) {
                    candidate.addAll(voices);
                }
            });
        }
        if (candidate.isEmpty()) {
            candidate.addAll(findSpecialKeyword(inputHistory));
        }
        return candidate;
    }

如果找到候選,就播放。

播放

為了防止同時播放多個語音,我們用一個單線程線程池來搞定。播放器使用javazoom.jl.player.Player

  /**
     * play in a single thread pool
     */
    static ExecutorService playerTheadPool;
	static {
        ThreadFactory playerFactory = new ThreadFactoryBuilder()
                .setNameFormat("player-pool-%d").build();
        playerTheadPool = new ThreadPoolExecutor(1, 1,
                0L, TimeUnit.MILLISECONDS,
                new LinkedBlockingQueue<>(1024), playerFactory, new ThreadPoolExecutor.AbortPolicy());
    }
	
	public static void play(List<String> voices) {

        FartSettings settings = FartSettings.getInstance();
        if (!settings.isEnable()) {
            return;
        }
        // play in single thread
        playerTheadPool.submit(() -> {
            String file = voices.get(new Random().nextInt() % voices.size());
            try {
                InputStream inputStream = null;
                if (StringUtils.isEmpty(settings.getCustomVoicePackage())) {
                    inputStream = Context.class.getResourceAsStream("/build-in-voice-chinese/" + file);
                } else {
                    File mp3File = Paths.get(settings.getCustomVoicePackage(), file).toFile();
                    if (mp3File.exists()) {
                        try {
                            inputStream = new FileInputStream(mp3File);
                        } catch (FileNotFoundException e) {
                        }
                    } else {
                        return;
                    }
                }
                if (inputStream != null) {
                    Player player = new Player(inputStream);
                    player.play();
                    player.close();
                }
            } catch (JavaLayerException e) {
            }
        });
    }

end

開源地址: https://github.com/jadepeng/idea-rainbow-fart

歡迎大家點贊!

作者:Jadepeng
出處:jqpeng的技術記事本–http://www.cnblogs.com/xiaoqi
您的支持是對博主最大的鼓勵,感謝您的認真閱讀。
本文版權歸作者所有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接,否則保留追究法律責任的權利。

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

※網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

※想知道最厲害的網頁設計公司"嚨底家"!

※幫你省時又省力,新北清潔一流服務好口碑

※別再煩惱如何寫文案,掌握八大原則!

新演算法估計:熱帶非洲植物1/3瀕臨滅絕

環境資訊中心綜合外電;姜唯 編譯;林大利 審校

本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※帶您來了解什麼是 USB CONNECTOR  ?

※自行創業 缺乏曝光? 下一步"網站設計"幫您第一時間規劃公司的門面形象

※如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!!

※綠能、環保無空污,成為電動車最新代名詞,目前市場使用率逐漸普及化

※廣告預算用在刀口上,網站設計公司幫您達到更多曝光效益

※教你寫出一流的銷售文案?

攜手戴姆勒 高通進軍電動車無線充電技術

高通宣布與戴姆勒(Daimler AG)進行戰略合作,共同推進連網汽車,將一同開發電動車無線電力傳輸方案。在首期合作中,雙方將聚焦在變革未來汽車,藉由行動裝置提升車內體驗及車輛性能,包括 3G/4G 連網、車內無線充電技術,並建置高通 Halo 電動車無線充電技術(WEVC)。此外,雙方亦將一同評估高通技術公司最新開發的車用解決方案。   高通與戴姆斯攜手並進,開發電動車「無線電力傳輸 2.0(Wireless Power Transfer2.0)」高性能方案。高通 Halo WEVC 技術藉一小型車用套件組,提供高性能與高功率,方便戴姆勒車主不需插座,也可為電動車與油電混合車充電。此外,藉由高通 WiPower 技術,使消費性電子產品能在車內進行無線充電。  

本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※帶您來了解什麼是 USB CONNECTOR  ?

※自行創業 缺乏曝光? 下一步"網站設計"幫您第一時間規劃公司的門面形象

※如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!!

※綠能、環保無空污,成為電動車最新代名詞,目前市場使用率逐漸普及化

※廣告預算用在刀口上,網站設計公司幫您達到更多曝光效益

※教你寫出一流的銷售文案?

BMW與日產將在南非建充電站 可望採再生能源供電

據路透社報導,BMW集團和日產汽車計畫在南非建設快速充電站網路,以推動當地電動車(含純電動車和插電式混動車)的銷量增長。   兩家公司表示,充電站的建設工作將從今年開始,並將持續至2017年,屆時BMW和日產旗下的電動車均可以在充電站進行充電,另外兩家公司還將在部分地區的充電站配備使用交流電的充電器。   目前南非正面臨電力供應短缺的困擾,不過BMW和日產稱充電站建設計畫不會受到影響。日產發言人Veralda Schmidt稱,未來兩家公司還可能採用可再生能源解決充電站供電問題。

本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※為什麼 USB CONNECTOR 是電子產業重要的元件?

※網頁設計一頭霧水??該從何著手呢? 找到專業技術的網頁設計公司,幫您輕鬆架站!

※想要讓你的商品成為最夯、最多人討論的話題?網頁設計公司讓你強力曝光

※想知道最厲害的台北網頁設計公司推薦、台中網頁設計公司推薦專業設計師”嚨底家”!!

※新北清潔公司,居家、辦公、裝潢細清專業服務

劍指特斯拉?通用將舉辦「EV Day」公布電動化戰略

美國最大汽車製造商通用汽車(General Motors),預定於美國東部時間 3 月 4 日舉辦「EV Day」會議,向投資人說明未來的全面電動化戰略藍圖,被認為意在挑戰特斯拉(Tesla)的龍頭地位。

CNBC、美國投資媒體 The Motley Fool 報導,通用成立至今已有 110 多年歷史,這家老牌車廠希望透過「EV Day」向外界表明,已準備好跨入電動化新時代,與電動車大廠特斯拉抗衡。

報導指出,「EV Day」受到通用執行長 Mary Barra 和總裁 Mark Reuss 等高層的高度重視。據知情人士透露,通用此次將展示 12 款即將上市的車型,數量之多,可說是不尋常的舉動,另也將發表新一代電動車平台、總體策略和充電基礎設施計畫等。

在此之前,通用對外宣布,旗下豪華汽車品牌凱迪拉克(Cadillac)將轉型為電動化品牌,引領該公司邁向全電動化。通用預計,在 2021 年前,將以每 6 個月平均 1 台的速度推出新車型。

2017 年底,通用宣示將在 2023 年前推出 20 款純電動車,但目前為止,僅在中國市場推出 3 款電動車,並在美國推出唯一一款純電動車 Chevrolet Bolt。

2 日通用股價跳漲 3.02%、收 31.42 美元;年初以來,通用股價累計重挫 14.15%,遜於大盤標普 500 指數同期下跌 4.35%。

通用 2 月 5 日公布的 2019 年第四季財報顯示,去年工會發動長達 40 天罷工,導致第四季調整後的稅息前獲利(EBIT-adjusted)損失 26 億美元,稀釋後每股盈餘減少 1.39 美元,全年稅息前獲利損失 36 億美元。

展望 2020 年,通用預計獲利不會明顯成長,調整後稀釋每股盈餘預估為 5.75 至 6.25 美元,與 2019 年持平,主要受美國與中國汽車市場放緩影響。

(本文內文由  授權使用;首圖來源: CC BY 2.0)

 

本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!!

※網頁設計一頭霧水??該從何著手呢? 找到專業技術的網頁設計公司,幫您輕鬆架站!

※想知道最厲害的台北網頁設計公司推薦、台中網頁設計公司推薦專業設計師”嚨底家”!!

※幫你省時又省力,新北清潔一流服務好口碑

※別再煩惱如何寫文案,掌握八大原則!

福斯首款電動休旅車定名 ID. 4,最高續航達 500 公里,2020 年底開賣

福斯汽車今日正式公開集團首款純電跨界休旅車,並定名為 ID. 4,官方宣稱滿電續航力將可接近 500 公里,預計於 2020 年底在歐洲首賣。

福斯車迷久等了,VW 集團從 2017 年展示 ID 家族概念車以來,今天終於定案首款跨界休旅車。在概念車時期,這款小型休旅車被稱為 Crozz,代表 crossover 的意思,現在它將正式被稱為 ID. 4。

 

看車之前,我們忍不住要吐槽一下福斯的命名哲學,在 ID 家族中,包含了 Crozz、Buzz、Vizzion、Buggy 和 Roomzz,這個太過裝可愛的疊字命名系統,背後的意義也相當直白,例如 Buzz,就是小巴士;Roomzz 就是擁有大空間的休旅車。

這些名字大概很難吸引消費者的購車衝動,目前看來,福斯會在正式上市前幫他們改個名,脫離了疊字時期,開始進入學 1234 的階段,根據現有情報,第一輛上市的掀背車,也就是大家比較熟悉的 ID. 3 ,ID. 1 可能是類似 Polo 尺寸的小車,而今天定名的則是跨界休旅車 ID.4。

目前官方公開的資訊還很有限,已經確認的是:

  1. 滿電續航里程可達 500 公里(歐盟 WLTP 標準)
  2. 最高時速可達 180 km/h
  3. 最大輸出功率約 225 kW
  4. 將會有後輪驅動與全輪驅動兩種選項
  5. 將有 SUV 與 coupe 兩種外型選擇

更重要的是,ID.4 將在全球生產,2020 年底在德國茨維考工廠,隨後將在中國上海廠生產,預計 2022 年在美國投產。同時這也是福斯 ID 家族挑戰美國市場的第一款車,銷售狀況非常受矚目。

從市場來看,ID.4 將直接與 Tesla Model Y、Rivian R1S 和 Ford Mustang Mach-E 競爭,但是等到 ID.4 開始生產時,它的對手們應該都已經交出第一批車了,這也讓福斯在市場上處於被動位置。

但至少可以肯定的是福斯集團在電動車生產上,已經有集團內兩大品牌的經驗可供參考,包括保時捷 Taycan 和奧迪 e-tron,對福斯來說,電動車戰場不僅是產業轉型的關鍵戰役,更是洗白過去排氣造假醜聞的重要機會。

(合作媒體:。圖片來源:)

本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※帶您來了解什麼是 USB CONNECTOR  ?

※自行創業 缺乏曝光? 下一步"網站設計"幫您第一時間規劃公司的門面形象

※如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!!

※綠能、環保無空污,成為電動車最新代名詞,目前市場使用率逐漸普及化

※廣告預算用在刀口上,網站設計公司幫您達到更多曝光效益

※教你寫出一流的銷售文案?

Gogoro 3 Delight 全新開賣,漸層三色系挑戰騎美學,最低 53,980 元

Gogoro 今天正式發表了 Gogoro 3 Delight,採用新設計理念漸層流動配色,推出 3 款新色之外,也增加了一些實用功能,一起來看看這台新車吧。

Gogoro 3 系列推出以來,網路討論度一直很高,堪稱最實用的 Gogoro,但酷似史萊母的造型也顛覆了傳統機車設計的概念。現在他們將 Delight 的風格美學與 3 系列的實用元素結合,會不會有機會再創銷售佳績呢?

VERDE 綠。(圖片來源:Gogoro 提供)

ROSSO 紅。(圖片來源:Gogoro 提供)

ACQUA 藍。

首先看到 Gogoro 這次最著重主打的「漸層色」,實車看起來並不是真的漸層,而是拼貼,總共有三款設計分別是「ROSSO 紅」、「ACQUA 藍」和「VERDE 綠」,由義大利設計師 Beatrice 操刀,將日出時的薄霧、迷濛山色與暮光天色映射到車身上。

Gogoro 3 Delight 三款新色,圖片左邊就是即將進入交換站的新電池。

這些看起來粉粉的色系,跟 Gogoro 3 外殼的 PP 材質非常班配,即使刮傷也不會太明顯。(望向Gogoro 1 可愛又可憐的屁屁 )

Gogoro 3 Delight 這次還搭載了幾個實用設計與功能,像是輪胎從原本前 14 吋、後 13 吋胎改為前後 12 吋全天候胎,不分晴雨都有不錯表現,車身高度也因此降低到 75 公分,有助於操控更穩定。此外也搭載了倒車輔助系統,減少車主在擁擠的車格中上演大逃脫的機會。

不過新功能與新設計可不是免錢的,Delight 版本定價比 Plus 版高了 3,000 元,來到 78,980 元,如果用上最高規格補助(汰舊換新+煞車補助+基隆 24,000 元),最低價則是 53,980 元。如果是單純新購的話,則是花蓮與台東的 17,000 元補助最優惠,再加上煞車補助的 1,000 元,購車價為 60,980 元。

詳細購車方案,可以到官網試算:

雖然價格調漲,不過 Gogoro 這次也提出了購車贈禮,在 4 月底前購買全新 Gogoro 3 系列車款,可獲得 Gogoro 品牌特仕安全帽和機車專用藍牙耳機,此外在標準的兩年保固外,再加贈第三年延長保固,價值約 6,500 元新台幣,還算是有誠意。

除了 Delight 版新車發行外,好不容易請設計師調出的配色,可不能只用在這,根據內部人員透露,近期也將會有彩色版電池進入換電站,運氣好的車主就有機會拿到唷。(但電量是一樣的)

採用新配色的新電池,感覺比新車還好看?

最後 Gogoro 也配合防疫舉辦活動,在 3/13~3/15 10:00~20:00,只要情侶穿著紅、藍、綠色系服裝共同前往 Gogoro 3 Delight 展覽區(台北市中山北路二段 26 巷 2 號 1 樓)拍照打卡,就可以獲得 Gogoro 騎士專用口罩一對;3/14 當天參加活動,還可以獲得情人節花束跟燭光晚餐抽獎機會,有興趣的朋友可以去現場逛逛唷。

(合作媒體:。首圖來源:Gogoro 提供)

本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※為什麼 USB CONNECTOR 是電子產業重要的元件?

※網頁設計一頭霧水??該從何著手呢? 找到專業技術的網頁設計公司,幫您輕鬆架站!

※想要讓你的商品成為最夯、最多人討論的話題?網頁設計公司讓你強力曝光

※想知道最厲害的台北網頁設計公司推薦、台中網頁設計公司推薦專業設計師”嚨底家”!!

※新北清潔公司,居家、辦公、裝潢細清專業服務

中國國家電網啟動新一輪充電樁建設,規模年增逾 10 倍

經濟參考報報導,中國兩大電網公司啟動新一輪充電樁建設。中國國家電網昨(14)日宣布,今(2020)年計畫安排充電樁建設投資27億元(人民幣,下同),新增充電樁7.8萬個,新增建設規模年增逾10倍。南方電網先前已公布,計畫未來4年投資251億元建設充電設施。業內人士指出,隨著「新基建」加速落實,電網公司充電樁的大規模建設,將對行業整體投資帶來巨大拉動作用,預計未來5年充電樁設備市場有望達到1,221億元。

據中國國家電網獲悉,昨集中聯動開工建設的126個充電設施項目,分布北京、天津、河北、上海、江蘇、浙江、湖南、青海等中國18個省(直轄市),投資規模3.6億元,計劃建設充電樁2,000多台,總設計充電容量109MW,可為約1.2萬輛商用、乘用電動汽車提供充電服務,直接帶動汽車購置消費30億元,並帶動電源類產品、零配件生產製造、車後服務等上下游產業需求。國家電網有關負責人表示,此次項目將創新展開專用充電站建設,聚焦集中式充電樁和快速充電樁,支持公交、物流、出租、重卡等專用車輛電動化革新。

數據顯示,截至目前為止,中國國家電網累計建成充換電站1.16萬座、充電樁9.58萬個。其中,高速公路快充站2,022座、充電樁8,270個,形成「十縱十橫兩環」高速公路快充網絡,覆蓋高速公路4.9萬公里,遍布19個省的171個城市。

而南方電網也在加緊布局,截至2019年底,南方電網已累計投資31.8億元、自建充電樁3.16萬個;2020年1-3月累計投資充電基礎設施近3,000萬元,計劃全年投資12億元建設充電基礎設施。而近期重點在粵港澳大灣區、海南自貿區及桂、滇、黔重點城市布局集中式充電站,實現南方五省區城際高速公路快速充電網絡全覆蓋。

中證報引述華泰證券指出,在「新基建」和補貼帶動下,中國充電樁建設需求有望提升,國網將成為此輪充電樁建設主力,大功率直流充電樁製造商將直接受益,充電樁核心功率模組亦受益於充電樁市場回暖。

興業證券則表示,2019年中國全國新能源汽車公共充電樁保有量約51.3萬個,相比新能源汽車約381萬輛的保有量仍有較大缺口,充電樁建設大規模重啟,將成為新能源汽車市場進一步發展的重要基礎,推動新能源汽車行業持續快速發展;看好已通過國網招標認證的公司將率先受益。

(本文內容由 授權使用。首圖來源:)

本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!!

※網頁設計一頭霧水??該從何著手呢? 找到專業技術的網頁設計公司,幫您輕鬆架站!

※想知道最厲害的台北網頁設計公司推薦、台中網頁設計公司推薦專業設計師”嚨底家”!!

※幫你省時又省力,新北清潔一流服務好口碑

※別再煩惱如何寫文案,掌握八大原則!