引言: Angular + Typescript + Webpack這套技術棧在工做中一直在用, 可是從0開始搭建起webpack的前端工程化基礎還歷來沒有本身作過, 遇到一些問題老是稀裏糊塗. 一直想從0開始搭建 angular的webpack打包工程.css
npm版本: v6.13.4
node版本: v12.16.1html
npm install -g @angular/cli ng new angular-webpack
生成了angular-webpack目錄, 可是此工程是用angular-cli來啓動的.前端
const path = require('path'); module.exports = { entry: { main: './src/main.ts', }, output: { filename: '[name].[hash].js', path: path.resolve(__dirname, 'dist'), } }
有webpack.config.js文件, 並不能直接使用, 須要安裝webpacknode
npm install webpack webpack-cli rimraf --save-dev
/*package.json*/ "pack": "rimraf dist/\* && webpack",
試試打包看看webpack
ERROR in ./src/main.ts Module not found: Error: Can't resolve './app/app.module' in '/Users/chenhua/CodeBase/angular-webpack/src' @ ./src/main.ts 4:0-45 10:41-50
webpack默認只會去解析js文件,因此尋找app.module.js沒找到就報錯, 而實際上咱們是app.module.ts文件web
resolve:{ extensions:[ '.js', '.ts'], }
運行再次報錯:typescript
ERROR in ./src/app/app.module.ts 8:0 Module parse failed: Unexpected character '@' (8:0)
緣由是@NgModule不能解析, 裝飾器語法 須要用typescript的loader來解析npm
到此, 可以生成打包文件,下一個問題是怎麼把打包後的js放入index.html中?json
使用html-webpack-plugin將output打包好的js文件,以script標籤的形式插入到一個index.html文件中,咱們須要咱們本身的index.html文件用於angular的啓動,因此給html-webpack-plugin配置上template.前端工程化
const HtmlWebpackPlugin = require( 'html-webpack-plugin'); plugins: [ new HtmlWebpackPlugin({ template: './src/index.html', }), ],
在瀏覽器中打開index.html,network顯示文件獲取不到bundle文件
file:///main.715b027541305761cdd9.js //如此獲取文件失敗
問題分析:直接打卡使用file協議請求, /bundle.js請求不到,
Uncaught Error: Can't resolve all parameters for e: (?). at Vt (main.715b027541305761cdd9.js:978) at e._getDependenciesMetadata (main.715b027541305761cdd9.js:1435) at e._getTypeMetadata (main.715b027541305761cdd9.js:1435) at e.getNgModuleMetadata (main.715b027541305761cdd9.js:1435) at e.getNgModuleSummary (main.715b027541305761cdd9.js:1435)
問題分析: webpack打包的時候自動進行了命名優化,看不出問題所在
/*mode: "development"不會對打包文件進行命名優化, 因此可以看到更準確的問題*/ Uncaught Error: Can't resolve all parameters for ApplicationModule: (?).
問題分析:通過了解, 須要加入reflect的polyfills
entry: { polyfills: "./src/polyfills.ts", main: "./src/main.ts", }, /*polyfills.ts中手動加入,core-js注意版本, 不然可能找不到es7/reflect, core-js: 2.6.0*/ import 'core-js/es7/reflect';
配置polyfills以後,仍然報錯:
Unhandled Promise rejection: Failed to load app.component.html
問題分析: 由於沒有正確的打包到app.component.html,因此加入angular2-template-loader用於加載組件的template文件
use:\[{ loader: 'angular2-template-loader', }\]
ERROR in ./src/app/app.component.html 1:0 Module parse failed: Unexpected token (1:0) 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
問題分析: html文件缺乏對應的loader
{ test: /\.html?$/, use: [ { loader: 'html-loader', } ], },
繼續訪問,報錯:
compiler.js:6070 Uncaught Error: Expected 'styles' to be an array of strings. at assertArrayOfStrings (compiler.js:6070) at CompileMetadataResolver.getNonNormalizedDirectiveMetadata (compiler.js:21995) at CompileMetadataResolver.\_getEntryComponentMetadata (compiler.js:22655)
問題分析: css文件沒有正確打包,
{ test: /\.css$/, use: ['to-string-loader', 'style-loader', 'css-loader'], }
Bingo!!