Проблема:
Вы используете Webpack для обслуживания своего кода в режиме dev-localhost, но хотите, чтобы вызовы API-интерфейсов SPA направлялись на прокси-сервер.
Пример:
Ваш webpack-dev-сервер обслуживает код по адресу http: // localhost: 9000 /, но ваш серверный api работает по адресу http: // localhost: 3000 / api /. Когда ваш SPA загружается, он пытается получить код из http: // localhost: 9000 / api / - как мы можем это исправить?
Запустите webpack-dev-server
Сначала настройте Webpack-dev-server. Из моей серии Использование Webpack с устаревшим Angular у нас есть репозиторий github, который уже настроен для серверного кода веб-пакета.
./node_modules/.bin/webpack-dev-server --config webpack.config.js --watch
SPA обслуживается из порта 9000
Project is running at http://localhost:9000/ webpack output is served from / Content not from webpack is served from /Users/thinkjones/dev/GeneConroyJonesArticles/webpack_plunge/dist
Добавить воображаемый сервер API
Итак, давайте добавим api, работающий на другом порту. Самый быстрый способ серверить json на конечной точке api - использовать отличный json-server. Первая установка:
npm install --save-dev json-server
Затем создайте файл db.json:
{ "posts": [ { "id": 1, "title": "json-server", "author": "typicode" } ], "comments": [ { "id": 1, "body": "some comment", "postId": 1 } ], "profile": { "name": "typicode" } }
Теперь мы можем запустить сервер так:
./node_modules/.bin/json-server --watch сервер / db.json
\{^_^}/ hi! Loading server/db.json Done Resources http://localhost:3000/posts http://localhost:3000/comments http://localhost:3000/profile Home http://localhost:3000 Type s + enter at any time to create a snapshot of the database Watching...
Но мы хотим обслуживать конечные точки из / api / blah, поэтому давайте использовать Node для настройки сервера. Добавить server / server.js
// server.js var jsonServer = require('json-server') var server = jsonServer.create() var router = jsonServer.router('server/db.json') var middlewares = jsonServer.defaults() server.use(middlewares) server.use('/api', router) // Rewrite routes to appear after /api server.listen(3000, function () { console.log('JSON Server is running') })
Теперь запустите сервер с узлом:
node server/server.js
Как это просто и круто!
Два сервера
Подводя итог, у нас есть код, обслуживаемый с: http: // localhost: 9000 / и api по адресу http: // localhost: 3000 / api / posts.
Затем давайте изменим наше приложение Angular для запроса данных из API.
Запросить GET из API.
На нашей целевой странице мы попытаемся получить сообщения из API-интерфейса, который дает нам:
myApp.controller('LandingCtrl', function($http){ var app = this; app.greeting = 'Welcome to the Landing Page'; $http.get('api/posts').then(function(response){ app.posts = response; }); });
А затем шаблон для отображения сообщений:
<div> <h1>Landing Page</h1> {{ctrl.greeting}} <a ui-sref="about"><< To the about page</a> <div ng-repeat="post in ctrl.posts"> {{post.id}}:{{post.title}} by {{post.author}} </div> </div>
Но когда мы запускаем этот код, мы получаем:
Как и ожидалось, это не удается, потому что наш api работает на порту 3000, а не на 9000, и поскольку мы использовали относительные URL-адреса в запросе Angular $ http, по умолчанию он указывает на то, откуда код обслуживается.
Решение 1. Давайте просто перепишем URL-адреса в клиентском коде.
Errr Нет, не надо! Но для иллюстрации:
myApp.controller('LandingCtrl', function($http){ var app = this; app.greeting = 'Welcome to the Landing Page'; $http.get('http://localhost:3000/api/posts').then(function(response){ app.posts = response.data; }); });
Множество причин, по которым мне лично это не нравится, и все они связаны с необходимостью динамически управлять основой запроса с помощью комбинаций http (s), сервера и порта. Кроме того, теперь мы засоряем наш код информацией о том, где установлено приложение, что затрудняет управление развертыванием тестовых кластеров и запуском на разных серверах.
Так есть ли другой способ?
Решение 2. Используйте http-proxy-middleware для прокси-запросов к API.
Сервер разработки Webpack использует« http-proxy-middleware , чтобы опционально проксировать запросы к отдельному, возможно внешнему, внутреннему серверу. Ниже приведен образец конфигурации ».
Добавьте свойство прокси в конфигурацию devServer в webpack.config.js:
devServer: { contentBase: path.join(__dirname, "dist"), compress: true, port: 9000, proxy: { '/api': { target: 'http://localhost:3000', secure: false } } }
Перезагрузите сервер webpack dev, и когда вы посетите сервер кода по адресу http: // localhost: 9000 / api / posts, вы увидите те же результаты, что и http: // localhost: 3000 / api / posts с сервера api. Ура!! И мы не засоряли наш код грязным кодом модификации основы URL.
Заключение
Это решение полезно для разработчиков, у которых есть код и конечные точки RESTful, обслуживаемые из двух разных мест. Это часто происходит, особенно когда вы используете инструменты JS для создания клиента, но, возможно, используете комбинации стилей Python-Flask, Java-Tomcat для обслуживания конечных точек RESTful. Это решение относительно простое и не требует изменения кода для управления различными средами развертывания.
Весь код на гитхабе здесь