當本身從土裏搭建起來一個網站,即便是最原始的那種網站,菜鳥如我也會遇到有許許多多瑣碎又細小的問題。本篇幅記錄關於代碼轉換和代碼打包相關工做。javascript
這兩個問題主要的矛盾在於,以前我一直是用<script>
來加載各種css,js,ico等文件的:
本地資源:css
<link="icon" href="http://www.xxxxxxxxx.top/icon/icon.ico"> <link="stylesheet" href="http://www.xxxxxxxxx.top/css/globalStyle.css type="text/css"> <script src="http://www.xxxxxxxxx.top/node_modules/socket.io-client/dist/socket.io.js"></script>
各種cdn:html
<script src="https://unpkg.com/react@16/umd/react.development.js" crossorigin></script> <script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js" crossorigin></script> <script src="https://cdn.bootcss.com/react-router/5.0.1/react-router.min.js"></script> <script src="https://cdn.bootcss.com/react-router-dom/5.0.1/react-router-dom.min.js"></script> <script src="//cdn.jsdelivr.net/npm/leancloud-storage@3.15.0/dist/av-live-query-min.js"></script>
有一天,有一些cdn崩了,致使網站無法用。我就想npm install
到本地吧,而後用import
加載各種文件。而後就遇到了各種問題,雖然最後解決方法看起來很簡單,但過程很艱辛、費時間,要是不寫一篇文章總感受時間花的太不值了。一方面給將來的本身查看起來方便,一方面但願能給有幸看到這篇文章的小夥伴們節約點時間。java
由於網站用的React
搭建的,React
的jsx語法
用起來很開心,但jsx
須要翻譯成js官方語法&瀏覽器認識的語法才能使用。React
官網推薦使用Babel
對jsx
進行翻譯。因此,那就Babel
咯~
node
babel
是一個JavaScript 編譯器,它將各種不一樣版本的javascript語言標準翻譯成你想要的版本。意思就是,最新版本的javascript語法,部分版本的瀏覽器不支持,須要轉換成低版本的javascript語法,才能實現兼容。引用Babel
官網的話:react
Babel
有這麼幾個主要的概念:Presets、Plugins、Config Files、Cliwebpack
Plugins,插件,是Babel
實現功能的主要模塊。經過安裝不一樣的插件,Babel
能夠實現不一樣的功能。web
例如:typescript
箭頭函數:() => {}
(ES6)轉換成低版本的函數申明class申明:class Heng extends Ha(){}
(ES6)轉換爲低版本的函數申明和原型鏈import/export
語法轉換成commonjs標準的require/export
jsx
語法轉換成React.createElement()
Plugins的使用,你只須要經過npm install 插件名稱
安裝一下,再經過配置文件+cli或者cli使用就ok了shell
Presets,預設,就是Babel
將各種插件整合在一塊兒,來提供一系列功能。
官方Presets:
Babel-7
版本出的預設,拋棄老版本繁亂的插件,這個預設經過配置能根據瀏覽器版本,將代碼自動翻譯成最適合的版本。React
作的預設,能很好的將React
簡便寫法翻譯成React
正經語法TypeScript
作的預設,只包含一個插件你也能夠本身作一個Presets:
把插件用數組組起來,文件取名myPreset.js
module.exports = function() { return { plugins: [ "pluginA", "pluginB", "pluginC", ] }; }
也能夠引用其它Presets
module.exports = () => ({ presets: [ require("@babel/preset-env"), ], plugins: [ [require("@babel/plugin-proposal-class-properties"), { loose: true }], require("@babel/plugin-proposal-object-rest-spread"), ], });
在配置Config Files中引用,npm模塊名或者相對路徑
{ "presets": ["babel-preset-myPreset"] }
{ "presets": ["./myProject/myPreset"] }
Presets的使用,你只須要經過npm install 預設名稱
安裝一下,再經過配置文件+cli或者cli使用就ok了
有不少方式使用Babel
,這裏就只介紹兩種,由於我就會這兩種😜
經過配置文件能夠配置Babel
用什麼插件、用哪一種預設、設置環境變量、忽略某一文件夾等。菜鳥如我簡單用用就設定用什麼插件和用哪一種環境變量就好了~
npm init
的地方,手動新建文件babel.config.json
or babel.config.js
或者.babelrc.json
。關於兩種區別,Babel
官網相關部分是這樣描述的:配置文件內容:babel.config.json
和.babelrc.json
{ "presets": ["presetName1","presetName2"], "plugins": ["pluginName1","pluginName2"] }
babel.config.js
module.exports = function (api) { api.cache(true); const presets = [ ... ]; const plugins = [ ... ]; return { presets, plugins }; }
接下來是Cli部分,命令行中輸入:
npx babel -w 原始文件地址/原始文件名 --out-file 輸出文件地址/輸出文件名
-w
表示監聽,--out-file
表示後面跟的是輸出文件信息。命令執行後,會自動調用配置文件中的相關配置。
純命令行模式使用
命令行中輸入:
npx babel script.js --out-dir lib --watch --out-file script-compiled.js --source-maps --ignore "src/**/*.spec.js","src/**/*.test.js" --presets=@babel/preset-env,@babel/flow --plugins=@babel/proposal-class-properties,@babel/transform-modules-amd
其實就是將配置文件中的配置全移到命令行內實現,利用--watch、--presets、--plugins、--ignore、--source-maps
等這樣的命令行參數。參數具體含義可參考Babel
官網相關內容。
爲何會用到webpack
呢?是這樣的。當我使用import
加載模塊名的時候,瀏覽器會報錯
加載模塊名:
import {HashRouter,Switch,Link,NavLink,Route,BrowserRouter} from "react-router-dom";報錯:
Uncaught TypeError: Failed to resolve module specifier "react-router-dom". Relative references must start with either "/", "./", or "../"
當我使用import
加載路徑/文件名的時候,瀏覽器會報錯
加載路徑/文件名:
import React from "./node_module/react/index.js";報錯:
Uncaught TypeError: Failed to resolve module specifier: "react"
export 'default' was not found in "./node_module/react/index.js"
嘛~具體的報錯內容不記得了,反正就是這個意思,瀏覽器老是會報錯。若是使用Babel
的智能翻譯預設@babel/preset-env
進行翻譯後,Babel
會將import
都翻譯成require
,這樣致使的結果仍是瀏覽器報錯:
翻譯前:
import React from "react";翻譯後:
var React = require("react");報錯:
ReferenceError: require is not defined
通過費時的尋找解決方案,我只能經過打包工具對import
和require
進行處理。webpack
那麼火,那就用webpack
吧~
webpack
就是JavaScript
靜態模塊打包器(static module bundler)。它能夠將各種資源import
到一塊兒,包括.css、.png、.xml、.js
等文件,而後「打包」生成一個新的js文件。新文件僅包含依賴的文件,而且可文件壓縮,還能代碼壓縮。
webpack
有這麼幾個主要的概念:Entry、Output、Loaders、Plugins、Mode
webpack
的使用很簡單。首先,建立一個配置文件webpack.config.js
,而後,執行打包命令npx webpack
。這樣就會在你指定的目錄下生成新的js文件,在你的html內引用這個js文件就ok了~
安裝
npm install webpack webpack-cli --save-dev
建立配置文件
const path = require('path'); module.exports = { entry: 入口文件, output: { path: 出口文件目錄, filename: 出口文件名 }, module: { rules: [ 各種loader配置項 ] }, plugins: [各種插件名], };
使用
npx webpack
Entry
用於在配置文件中配置打包入口。意思就是從Entry
開始,查找全部它的依賴,進行打包。經常使用格式以下:
module.exports = { entry: './path/to/my/entry/file.js' };
Output
用於在配置文件中配置打包後新文件的位置。經常使用格式以下:
const path = require('path'); module.exports = { entry: './path/to/my/entry/file.js', output: { path: path.resolve(__dirname, 'dist'), filename: 'my-first-webpack.bundle.js' } };
path
表示輸出文件的絕對路徑,__dirname
表示該配置文件所在的絕對路徑,filename
表示輸出的新文件名,path.resolve()
會將括號內的參數解析成一個完整的路徑、固然用以前須要引入nodejs
模塊:const path = require('path');
。如上述例子會打包輸出到__dirname/dist/my-first-webpack.bundle.js
Loaders
用以使webpack
可以加載打包非js文件。全部的Loaders
能夠查看官網。經常使用格式以下:
const path = require('path'); module.exports = { entry: './path/to/my/entry/file.js', output: { path: path.resolve(__dirname, 'dist'), filename: 'my-first-webpack.bundle.js' }, module: { rules: [ { test: 文件名正則, use: [ "loader-name" ] } ] } };
安裝
npm install --save-dev style-loader css-loader
修改配置文件
module: { rules: [ { test: /\.css$/, use: [ 'style-loader', 'css-loader' ] } ] }
使用
import './style.css';
file-loader
可用來加載圖片或者文字或者其它文件類型。
安裝
npm install --save-dev file-loader
修改配置文件
module: { rules: [ { test: /\.css$/, use: [ 'style-loader', 'css-loader' ] }, { test: /\.(png|svg|jpg|gif)$/, use: [ 'file-loader' ] }, { test: /\.(woff|woff2|eot|ttf|otf)$/, use: [ 'file-loader' ] } ] }
使用
入口文件:
import './style.css';
style.css:
@font-face { font-family: 'MyFont'; src: url('./my-font.woff2') format('woff2'), url('./my-font.woff') format('woff'); } .hello { font-family: 'MyFont'; background: url('./icon.png'); }
Plugins
,插件,用於幫助webpack
實現各類各樣的功能。以下例子clean-webpack-plugin
插件幫助清理文件夾,刪除不須要的依賴文件。
安裝
npm install clean-webpack-plugin --save-dev
修改配置文件
const path = require('path'); const CleanWebpackPlugin = require('clean-webpack-plugin'); module.exports = { entry: './path/to/my/entry/file.js', plugins: [ new CleanWebpackPlugin(['dist']), ], output: { path: path.resolve(__dirname, 'dist'), filename: '[name].bundle.js', } };
mode
用來在配置文件中指定環境:development
&production
。webpack
在不一樣環境下會加載不一樣的插件和處理方式。
修改配置文件
module.exports = { mode: "production", }
module.exports = { mode: "development", }
個人目標是將<script>
標籤儘量多的轉換成代碼內import
。一方面減小加載各種<script>
資源的時間,import
資源都安裝在服務器上,就只須要加載一個文件就ok了;一方面減小cdn不肯定的因素。
曾經的資源加載方式:
<script src="https://cdn.bootcss.com/react/16.8.6/umd/react.production.min.js"></script> <script src="https://cdn.bootcss.com/react-dom/16.8.6/umd/react-dom.production.min.js"></script> --> <script src="https://cdn.bootcss.com/react-router/5.0.1/react-router.min.js"></script> <script src="https://cdn.bootcss.com/react-router-dom/5.0.1/react-router-dom.min.js"></script> <script src="http://www.dogcatpig.top/js_rely/babel_min_6.26.0.js"></script>
上面babel
不須要import
,安裝預設@babel/preset-react
、新建配置文件babel.config.json
後、用命令npx babel -w 原始文件地址/原始文件名 --out-file 輸出文件地址/輸出文件名
輸出翻譯後文件。
可是,其它的資源雖然import/export
已是javascript語言標準了,但用起來仍是不行。因此須要webpack
,webpack
不只能處理import/export & require/export
,還能將各類資源打包到一個js文件中,極大的減小網站加載時間。親測若是沒緩存,至少減小一半時間,有緩存2毫秒左右。用法也很簡單,安裝你想要的loaders & plugins
,新建配置文件webpack.config.js
,用命令npx webpack
輸出。
😊文中配置文件均放置在package.json
同目錄😊